360 Secure SkillHub
360 安全技能中心

euthyna (English)

面向代码安全审计的裁决与交付把关技能:以 git 历史、覆盖率等确定性测量和六道闸门判断漏洞主张、变更回归与依赖风险,证据不足的主张降级为观察;报告必须写入指定文件并通过 gate 校验,无法测量的项一律记为不可评估。

modusensus
modusensus
热度 63.03
最近更新 2026-10-18 05:12:54
分类:安全依赖:代码执行 / 读写文件应用场景:代码审查 / 报告撰写

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add euthyna-en
Metadata
name
euthyna-en
description
The adjudication discipline and delivery gate for code security audits. Use when the user asks to audit the security of a piece of code, a pull request, a change, or to verify an existing vulnerability claim. It does three things: supply the deterministic facts a model cannot compute (callers, test coverage, git history origins), judge every claim against six gates, and downgrade any claim that cannot produce evidence to "observation" rather than a finding. Not for: asking about the details of a single CVE, running an existing scanner once, pure documentation or formatting changes, or when the user explicitly wants a quick summary and accepts the risk.
whenToUse
Use when the user asks to audit the security surface of code or a repository, verify whether a suspected vulnerability is real, decide whether a finding is exploitable, review whether a change introduces a security regression, or asks to "audit before delivery". For single-topic checks such as only searching for secrets or only checking dependency versions, use the dedicated specialist skill instead and do not trigger this one.
disable-model-invocation
true
user-invocable
true

euthyna — the adjudication discipline for code security audits

εὔθυνα: the audit every Athenian official had to submit on leaving office; you did not get to walk away without handing over your accounts. That is this skill's core mechanism: saying "the audit is done" does not count. Evidence is handed over and the gates decide.

This skill does not find bugs; it polices conclusions. Finding bugs is the model's and the existing tools' job. This skill's job: every conclusion must pass the gates, and a conclusion that cannot pass is downgraded to "observation".


When to use / when not to use

Use:

  • The user asks to audit the security surface of code, a repository, or a change (PR / commit / diff)
  • The user brings a suspected vulnerability and asks "is this real" or "is it exploitable"
  • The user asks to review whether a change weakened an existing security control
  • The user asks to "verify before delivery"

Do not use (refuse directly or route to another skill):

  • Only asking about a specific CVE or dependency detail → use a dependency audit tool
  • Only asking to run an existing scanner and paste its output → that is a tool call, not an audit
  • Pure documentation, formatting, or lint changes → no security surface
  • The user explicitly wants a quick summary and accepts the risk → state that this is "non-audit mode" and do not apply this skill's adjudication format

Three non-negotiable rules

These three rules are the entire difference between this skill and "tell the model to be more careful". No stage, no path may skip them.

Rule 1: measurable quantities come from commands, the model only interprets

Caller counts, test coverage, dependency versions, line numbers, commit hashes — none of these may be answered from impression. The model may say "not measurable" when a command is unavailable, but it must not estimate and then write the estimate into a conclusion as a fact.

This comes from a measured failure: a package showed "5+ maintainers" on the code hosting platform while the package manager's actual permission list had 1 person; another package with 160 million weekly downloads showed zero downloads in one data source. Estimating numbers by feel is always wrong.

Rule 2: evidence is mandatory down to file:line; placeholders are banned

  • Every claim cites a concrete location in the form path:L123, and path:L123 (commit abc1234) when a version exists
  • probably / likely / "roughly" are banned — chase the real code, and if you cannot, say you cannot
  • PoCs must not contain TODO, ..., or // attacker does something here
  • Once a PoC is found to use an artificial bypass (mock, stub, disabled check), that PoC is invalid

Rule 3: missing data is not clean

Every criterion falls into exactly one of three states: evaluated-clean / evaluated-flagged / not evaluable for a stated reason.

  • A run that measured nothing produces "not evaluable", not "no problems found"
  • Before citing any "clean" conclusion, read the coverage table first
  • Numbers must be quoted verbatim — no re-deriving, rounding, or dressing up
  • Finding nothing is not an endorsement

Entry decision tree

What did the user give?
│
├─ An existing suspected-vulnerability claim ──► Stage C: claim verification
│   ("is this real", "is it exploitable")          read references/verification-gates.md
│                                                 ★ if the conclusion depends on "was it tested" → run coverage
│
├─ A change (PR / diff / commit) ───────────────► Stage B: change audit
│   ("is this PR safe")                            read references/change-audit.md
│                                                 ★ first command: euthyna audit --base <fork point>
│                                                   (history + deps in one run, see below)
│                                                 ★ if test coverage matters   → then run coverage
│
├─ A repository / dependency surface ───────────► Stage A: dependency audit
│   ("do the dependencies have problems")          read references/dependency-audit.md
│
└─ A full repository security audit ────────────► Stage B as the core, with A and C as sub-steps

★ = run before reading code by hand, not as a follow-up after reading. The deterministic facts from the producers decide where the manual reading must be directed.

Multiple stages may run, but stages must not substitute for each other. In particular: every suspected finding reported by Stage B must go through Stage C one by one — never write it straight into the report as a conclusion.


The two deterministic measurements this skill ships

Callers, coverage, dependency vulnerabilities and secrets are not re-built (see the division of labor at the end). But two things nobody else does — and a model cannot compute reliably — are shipped by this skill as a zero-dependency CLI:

Measurement Question it answers When it is mandatory
audit Both questions below in one run (history traces original introducers by default + deps enumerates every lockfile dependency), one merged report the first command of every audit (opening Stage B)
history Which commit does the code this change deleted come from? Was that commit a security fix? when re-running history alone (e.g. a different --base)
coverage Was this symbol ever actually invoked by a test run? when the report claims "tested / not tested" (Stage B / C)
# the only required argument is --base (pre-change revision / PR fork point):
node <euthyna repo>/bin/euthyna.js audit --base <pre-change revision> --repo <audited repo>

# history / coverage run alone when needed:
node <euthyna repo>/bin/euthyna.js history  --base <pre-change revision> --repo <audited repo>
node <euthyna repo>/bin/euthyna.js coverage --coverage <absolute path to coverage file> --symbol <symbol name>

⚠️ A relative node bin/euthyna.js always fails. During an audit the current directory is the audited project, not the euthyna repo, and it will report Cannot find module. Use the euthyna repo's path and pass the audited repo explicitly with --repo (--base / --head resolve against it).

Exit codes — the difference between 2 and 0 is the reason this whole thing exists:

Code Meaning What to do
0 measured, no security-related finding continue, but read the "criteria not evaluated" section
10 measured, at least one fact classified security raise priority, run each through Stage C; do not treat as a conclusion
1 usage error fix the command. This is not a measurement result
2 could not measure at all must not be read as clean. Change the measurement approach, or mark the criterion "not evaluable"

When a command is unavailable (not installed, no checkout): mark the criterion "not evaluable" — never fill the gap with a hand estimate.

Operations manual (commands, real output samples, failure modes): references/fact-producers.md.

Execution discipline (reproduce commands and PoCs)

--verify and PoCs execute commands on the user's machine. Before running any reproduce/verification command:

  • Get the user's explicit approval first, listing the exact commands — never run an unannounced command
  • Prefer a sandbox or throwaway container (e.g. Docker) whenever one can run the command; when sandboxing is impossible, state the risk before running
  • A report's PoC is written for whoever receives the report; every command the agent itself runs during adjudication follows this same rule

The fact contract (the interface between measurement and adjudication)

This skill defines the interface between the measurement layer and the adjudication layer: docs/fact-contract.md.

Key points:

  • The contract carries only facts — no scores, no severity levels, no remediation advice
  • Every fact must carry a reproduce command or producing tool + version
  • Scores must not be used as gates (learned from dsh-trust-check: its contract explicitly says "do not use score or band as a gate")
  • approximate facts must not participate in gates
  • unknown is not "clean" — it is the most misused of the three states

How to read a fact (what it lets you infer, and what it does not): references/fact-contract.md.


The adjudication format

Whatever path was taken, the output must land in this shape:

BUG #N TRUE POSITIVE — [one-line claim]
  All gates passed. Evidence: path:L123 (commit abc1234)
  Reproduce: <re-runnable command or PoC location>
  Exploitability: EASY / MEDIUM / HARD
  Impact: specific to funds / elevated privilege / exposed data

BUG #N FALSE POSITIVE — [reason for rejection]
  Gate N (gate name) FAIL: <specific evidence>
  e.g. line 98's check guarantees packet_size >= 16, so (packet_size - header_size) >= 8.
       Underflow is mathematically impossible.

BUG #N INCONCLUSIVE — [reason it cannot be decided]
  Gate N (gate name) NOT EVALUATED: <why>

The third state INCONCLUSIVE must exist. Trail of Bits' original fp-check has only two states because it uses a Stop hook to force infinite continuation until completion; DSH cannot do that (the Stop hook must rate-limit itself or it loops forever, see docs/dsh-stop-gate.md). So this honest exit must exist — "not finished" must never be written as FALSE POSITIVE.


The programmatic gate check (euthyna gate)

The format above is not decoration: euthyna gate <report file> mechanically checks every finding —

  • TRUE POSITIVE: evidence must reach path:L123, a reproduce command is mandatory, impact must be stated, and all six gates must pass;
  • FALSE POSITIVE: at least one gate FAIL with specific evidence;
  • INCONCLUSIVE: at least one gate not evaluated, and no FAIL.

A finding that lacks evidence, lacks reproduction, or whose gates contradict its verdict (such as a TRUE POSITIVE carrying a FAIL gate) is downgraded to "observation" and reported with exit code 10 — the checker does the policing, no self-awareness required.

node <euthyna repo>/bin/euthyna.js gate <report file>
# re-run each reproduce command to verify (allowlisted tools, argv execution, no shell):
node <euthyna repo>/bin/euthyna.js gate <report file> --verify --cwd <audited repo>
  • Exit code 0 = everything passed; 10 = at least one finding downgraded; 2 = the report cannot be read / has no checkable finding.
  • Under --verify, a reproduce command that fails to run is also a downgrade — "I can reproduce it" is not a claim until the run actually succeeds.

Run euthyna gate on the report before handing it over. It validates the report's own self-declared claims; it does not audit the target repository — so it cannot replace adjudication, it only guarantees that a conclusion without evidence cannot leave as "established".


The report must be written to disk

  • Outputting only to chat is a failure. A report file is mandatory
  • Filename: <PROJECT>_EUTHYNA_AUDIT_<YYYY-MM-DD>.md
  • Fallback order when writing fails: current working directory → user desktop → temp directory → last resort only then output to chat and ask the user to save it manually

Pre-delivery self-check (tick every item; without all of them you may not say "audit done")

  • Every suspected finding went through complete Stage C, not "looked at it and it seems false"
  • Ran audit (or history when the diff has deleted lines); code deleted from a security-fix commit handled at highest risk
  • Every "tested / not tested" sentence in the report is backed by coverage output, or marked "not evaluable"
  • No criterion with exit code 2 appears in a "clean" column
  • Every conclusion carries a file:line
  • Every conclusion carries one of the three states (clean / flagged / not evaluable)
  • The coverage table states which criteria were not evaluated and why
  • All 13 devil's advocate questions answered (including the false-negative 12 and 13)
  • The report file has been written to disk
  • The report has passed euthyna gate (exit code 0; if there are downgrades, read why)
  • "Missing data" was not written as "clean"

Reference files

Load on demand. Do not read them all at once — progressive disclosure is why this stays effective in long sessions.

File Contents When to read
references/verification-gates.md Stage C: routing, the six gates, false-positive list, devil's advocate, PoC rules when judging an existing claim (most used)
references/change-audit.md Stage B: baseline, depth vs risk, origin attribution, blast radius, adversarial modeling when auditing a change
references/dependency-audit.md Stage A: manifests/lockfiles, the three states, report style, prohibitions when auditing the dependency surface
references/bug-classes.md Per-class checklists for 9 defect classes and their default assumption direction once the defect class is chosen
references/meta-mechanisms.md The six meta-mechanisms that keep the process from degrading into a formality read once at the start of an audit
references/fact-producers.md Operations manual: when to run the two measurements, how to write the commands, how to handle exit codes, real output samples, failure modes before running a producer (Stage B / C)
references/fact-contract.md Once you have a fact: what it lets you infer, and what it does not after reading a producer's output

The skill text is self-contained: every file above lives inside references/, depends on nothing outside the skill directory, and the whole directory can be copied into any skill root.

⚠️ But the producer is a separate program, not inside the skill directory. Copying the skill does not carry the CLI along. A new environment must install it separately, or ship a checkout of this project; otherwise the related criteria can only be marked "not evaluable" — which is an honest result, better than a hand estimate. See references/fact-producers.md section 1.


Division of labor with the existing ecosystem (no duplicated work)

Already built by someone else What euthyna does
Call graph / blast radius (dsh-tool-lens, dsh-blast-radius) does not rebuild, consumes their output
Coverage (dsh-code-coverage) does not rebuild, consumes its output
Dependency vulnerabilities (dsh-dep-vuln-scan etc.) does not rebuild, consumes its output
Secret scanning (dsh-code-security) does not rebuild, consumes its output
Delivery gate mechanisms (dsh-doublecheck, formalswarm) mechanisms worth borrowing; euthyna's gate content is the security-specific six gates
Evidence lifecycle and PoC lab (dsh-omv) can coexist: dsh-omv can be a consumer of the fact contract

euthyna only supplies the two deterministic measurements nobody else does (see docs/positioning.md §7.2): the mechanical adjudication of git security regressions, and the "symbol × real execution coverage" join.