euthyna 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,174 @@
1
+ # Meta-mechanisms: six things that make the process actually work
2
+
3
+ > Stages A / B / C are the **process**. This file is the **mechanisms** that keep the process from degrading into going through the motions.
4
+ >
5
+ > What they share: **none of them relies on self-discipline**. Any constraint that depends on "remember to be careful" fails in long sessions.
6
+
7
+ ---
8
+
9
+ ## 1. Against "wrong numbers": separate measurement from judgment
10
+
11
+ **Rule**: every measurable quantity is produced by a command or script. The model only interprets.
12
+
13
+ Number of callers, test coverage, dependency versions, line numbers, commit hashes, how many times a function is invoked —
14
+ **none of these may be answered from memory**. When a tool is unavailable, say "not measurable" —
15
+ **never estimate and then write the estimate into a conclusion as fact**.
16
+
17
+ ### Why this rule must be hardened
18
+
19
+ Model estimates of such numbers are not "slightly off" — they are **systematically wrong**, and wrong in a way nobody notices:
20
+
21
+ - a package shows 5+ maintainers on the code-hosting platform, while its actual permission list in the package manager has **1 person**
22
+ - a package downloaded 160 million times a week shows **zero downloads** in some data source
23
+
24
+ Both are real cases that failed in measurement. What they show is not "be more careful" — it is
25
+ **estimating numbers by feel is unreliable no matter how hard you try**.
26
+
27
+ ### How it is implemented
28
+
29
+ For this, the project provides producers and defines the contract (`fact-contract.md`):
30
+
31
+ ```powershell
32
+ # <euthyna repo> = where this project is checked out, not the audited project's path
33
+ node <euthyna repo>/bin/euthyna.js history --base <rev> --repo <audited repo>
34
+ node <euthyna repo>/bin/euthyna.js coverage --coverage <file> --symbol <name>
35
+ ```
36
+
37
+ ⚠️ Writing the relative `node bin/euthyna.js` fails: during an audit the current directory is the audited project.
38
+ Commands, exit codes, and failure modes: see `fact-producers.md`.
39
+
40
+ ---
41
+
42
+ ## 2. Against "fabricated findings": evidence enforcement + the barrier dichotomy
43
+
44
+ ### 2.1 Enforce evidence down to `file:line`
45
+
46
+ - every claim cites a concrete location: `path:L123`, or `path:L123 (commit abc1234)` when a version exists
47
+ - `probably` / `likely` / "roughly" are banned — chase the real code; when you cannot, **say you cannot**
48
+ - no `TODO`, `...`, or `// the attacker does something here` in demonstration code
49
+ - **the moment a demonstration uses an artificial bypass** (mock, stub, disabled check), that demonstration is judged **invalid**
50
+
51
+ ### 2.2 "Raising the bar" is not "eliminating the defect"
52
+
53
+ This is the easiest point to confuse, and the easiest place to overestimate severity. Protections fall into two classes:
54
+
55
+ | Class | Example | Meaning |
56
+ |---|---|---|
57
+ | **fully prevents** | Rust's safe type system against memory corruption; parameterized queries against SQL injection | that class of defect cannot occur |
58
+ | **only raises the bar** | ASLR, stack canaries, CFI | harder, but **not eliminated** |
59
+
60
+ Likewise, keep apart:
61
+
62
+ - **primary security control** vs **defense in depth** — when the primary protection is intact, a failing defense-in-depth layer is **not a defect**
63
+ - **mathematically impossible** / **practically infeasible** / **feasible** — the three states must be stated clearly, not conflated
64
+
65
+ ---
66
+
67
+ ## 3. Against "missing the real thing": two-way skepticism + three-state honesty
68
+
69
+ A system that only guards against false positives degenerates into "nothing is ever a defect" — as useless as "everything is a defect".
70
+
71
+ ### 3.1 The devil's advocate must work both ways
72
+
73
+ Besides the questions arguing against a defect (guarding against false positives), these two **must** also be asked:
74
+
75
+ > **12. Did I dismiss a real defect because the exploitation is complex or unlikely?**
76
+ > **13. Did I invent mitigations or validation logic that I did not verify in the source?** (**re-read the code** after concluding)
77
+
78
+ Questions 12 and 13 must be asked **in every case**. The model's default bias is "report too much", so most mechanisms suppress it;
79
+ **over-suppressing misses real vulnerabilities** — these two questions are the symmetric counterweight.
80
+
81
+ ### 3.2 Three states, not two
82
+
83
+ Every criterion lands in exactly one of: **evaluated · clean / evaluated · flagged / not evaluable for a stated reason**.
84
+
85
+ - a run that measured nothing produces "not evaluable", **not** "no issues found"
86
+ - before citing any "clean" conclusion, look at the coverage table first
87
+ - **numbers must be quoted verbatim** — no re-deriving, no rounding, no dressing up
88
+ - **finding nothing is not an endorsement**
89
+
90
+ ### 3.3 Verdicts need a third state
91
+
92
+ With only "true / false" states, "not finished checking" is forced to be written as "false" — that manufactures false negatives.
93
+
94
+ So verdicts must have `INCONCLUSIVE`, and **must state what is missing and why it is missing**.
95
+
96
+ ---
97
+
98
+ ## 4. Against "laziness": enumerate the excuses in advance
99
+
100
+ **"Be careful" is useless. What works is listing in advance the lazy impulses a model will produce in a real audit, and shutting each one down.**
101
+
102
+ | Excuse | Why it is wrong | What you must do |
103
+ |---|---|---|
104
+ | the change is small, take a quick look | the most severe historical vulnerabilities can be two lines | classify by **risk**, not by size |
105
+ | I know this codebase | familiarity creates blind spots | establish a baseline explicitly |
106
+ | digging through git history takes too long | history reveals regressions | origin attribution is **not skippable** |
107
+ | the impact is obvious at a glance | transitive callers get missed | compute quantitatively |
108
+ | missing tests are not my problem | missing tests = escalated risk | write it in the report and **raise** the severity |
109
+ | it is just a refactor, no security impact | refactors break invariants | analyze as high risk until **proven** low risk |
110
+ | I can explain it verbally | no artifact = lost findings | a report file is mandatory |
111
+ | this pattern looks dangerous | pattern recognition is not analysis | no conclusion without completing the data-flow trace |
112
+ | similar code elsewhere is a vulnerability | context, callers, and protections differ per site | verify this instance independently |
113
+ | this is obviously a severe vulnerability | the model is biased toward seeing bugs and overestimating severity | complete the devil's advocate review and prove it with evidence |
114
+ | skip full verification to save time | partial analysis is not allowed | execute **all** steps of the chosen path |
115
+
116
+ **This table must be explicitly loaded at the start of every audit**, and it **grows with real incidents** —
117
+ every new lazy pattern found adds a row. It is a living list.
118
+
119
+ ---
120
+
121
+ ## 5. Against "loss": output must be written to disk
122
+
123
+ - **output to chat only counts as failure**. a report file must be written
124
+ - fallback order when writing fails: current working directory → desktop → temp directory → **last resort** only: output to chat and prompt for manual saving
125
+ - filenames carry the project name and date
126
+
127
+ Design intent: chat transcripts scroll away and get compressed; **files do not**. A deliverable's survival should not depend on session length.
128
+
129
+ ---
130
+
131
+ ## 6. Against "contamination": isolate capabilities by stage
132
+
133
+ ### 6.1 Gates must not be delegated
134
+
135
+ Some stages need **cross-stage integrated judgment**; handing them to a subagent shreds the responsibility:
136
+
137
+ - impact assessment
138
+ - devil's advocate review
139
+ - gate adjudication
140
+
141
+ **These three must not be delegated.**
142
+
143
+ ### 6.2 Subagent permissions are deliberately asymmetric
144
+
145
+ | Role | Permission |
146
+ |---|---|
147
+ | data-flow analysis | **read-only** |
148
+ | exploitability verification | **read-only** |
149
+ | PoC building | the only one that may write |
150
+
151
+ Rationale: **the ability to manufacture evidence is concentrated in a single stage**. Earlier stages may only observe —
152
+ if the analysis stage could write files, it could "conveniently" reshape the evidence to support its own conclusions.
153
+
154
+ ### 6.3 Never start the next stage before dependencies are done
155
+
156
+ Mark tasks in-progress when they start; **only concrete evidence marks them completed**.
157
+ Parallel substages start concurrently; before entering the next dependent gate, **collect all results**.
158
+
159
+ ---
160
+
161
+ ## How the six relate
162
+
163
+ ```
164
+ 1. separate measurement from judgment ─┐
165
+ ├─→ makes "facts" trustworthy
166
+ 2. evidence enforcement ────────────────┘
167
+ ├─→ makes "conclusions" trustworthy
168
+ 3. two-way skepticism ──────────────────┘
169
+ 4. excuse table ───────────────────────────→ keeps the process from being bypassed
170
+ 5. written to disk ────────────────────────→ keeps output alive
171
+ 6. capability isolation ───────────────────→ keeps the process from being contaminated
172
+ ```
173
+
174
+ The first three decide **conclusion quality**; the last three decide **process quality**. Missing any one, and the whole thing degrades at some point.
@@ -0,0 +1,291 @@
1
+ # Stage C: claim verification (adjudication layer)
2
+
3
+ > **Role**: it does not find bugs — it only adjudicates whether an existing suspected bug is real.
4
+ > Trigger phrases: "is this true", "verify this finding", "is it exploitable".
5
+ >
6
+ > This file is euthyna's core asset. Anyone can do the measurement layer; **adjudication discipline is the differentiator**.
7
+ > Methodology source and license: see `NOTICE.md`.
8
+
9
+ ---
10
+
11
+ ## C.0 Step zero: restate the claim (not skippable)
12
+
13
+ Restate it in your own words, item by item, in writing. **No jumping straight into analysis.**
14
+
15
+ | What to restate | What to cover |
16
+ |---|---|
17
+ | Exact vulnerability claim | One sentence, decidable as true or false |
18
+ | Claimed root cause | Where the defect is, and **why** |
19
+ | Claimed trigger path | What the attacker does |
20
+ | Claimed impact | Lands on RCE / privilege escalation / information disclosure |
21
+ | **Threat model** | What privileges does the code run with? Is it sandboxed? What can the attacker already do before triggering? |
22
+ | Defect class | One of the 9 classes (see `bug-classes.md`) |
23
+ | Execution context | Single-threaded? Synchronized? Lifecycle? |
24
+ | Caller analysis | Who calls it, and with what arguments |
25
+ | Architecture context | Where it sits in the system |
26
+ | Historical context | When and why this code was added |
27
+
28
+ > **Half of all false positives collapse at this step** — when the claim is restated precisely, it simply does not hold together.
29
+ > So this is not formalism: it is the highest-value filter.
30
+
31
+ **Output**: write the restatement as `subject.claim` in the fact contract (see `docs/fact-contract.md`).
32
+
33
+ ---
34
+
35
+ ## C.1 Routing: standard verification vs deep verification
36
+
37
+ ### Standard verification (linear single-pass checklist) — **all** must hold
38
+
39
+ - The claim is clear and specific
40
+ - Single component (no cross-component interaction)
41
+ - The defect class is known
42
+ - No concurrency or async
43
+ - The data flow is straightforward
44
+
45
+ ### Deep verification (task-based orchestration + subagents) — **any** one triggers it
46
+
47
+ - The claim is vague or has multiple readings
48
+ - Cross-component (data flows through 3+ modules)
49
+ - Involves race conditions or TOCTOU
50
+ - A logic defect with no clear spec to compare against
51
+ - Standard verification cannot reach a conclusion, or was escalated
52
+ - The user explicitly asks
53
+
54
+ **Start with standard by default.** Standard verification has two built-in escalation checkpoints:
55
+
56
+ 1. After Step 1: if more than 3 trust boundaries, callback/async control flow, or an ambiguous validation chain appear → escalate
57
+ 2. After Step 5: if any issue leaves unresolvable genuine uncertainty → escalate
58
+
59
+ **On escalation, hand over all evidence gathered so far** — deep verification continues from where it stopped and **does not redo completed work**.
60
+
61
+ ---
62
+
63
+ ## C.2 The 6 steps of standard verification
64
+
65
+ ### Step 1: data flow
66
+
67
+ 1. Map the trust boundaries crossed (internal trusted vs external untrusted)
68
+ 2. Identify **all** validation and sanitization between source and sink
69
+ 3. Check API contracts — some APIs carry their own boundary protection
70
+ 4. Check environmental defenses, and **distinguish** "fully prevents" from "only raises the bar"
71
+ 5. Apply the class-specific checks for the defect class (`bug-classes.md`)
72
+
73
+ > **Pitfall: analyzing code in isolation.** Upstream conditional logic can make the defect mathematically unreachable.
74
+ > You must follow the full validation chain — not just the few lines around the dangerous operation.
75
+
76
+ ### Step 2: exploitability
77
+
78
+ - **Attacker-controlled**: internal storage written by trusted components is **not** attacker-controlled
79
+ - **Boundary proof**: write out an explicit algebraic proof verifying "IF the check passes THEN the boundary guarantee holds"
80
+ - **Race feasibility**: single-threaded initialization and synchronized contexts **cannot** race
81
+
82
+ ### Step 3: impact
83
+
84
+ - Distinguish **real security impact** (RCE, privilege escalation, information disclosure) from **operational robustness** (crash recovery, cleanup failures)
85
+ - Distinguish **primary security controls** from **defense in depth**
86
+
87
+ ### Step 4: demonstration sketch
88
+
89
+ ```
90
+ Data flow: [Source] → [validation?] → [transformation?] → [fragile operation] → [impact]
91
+ ```
92
+
93
+ Write down: what the attacker controls, how, and the triggering pseudocode.
94
+
95
+ ### Step 5: devil's advocate spot-check (7 questions)
96
+
97
+ 5 opposing questions (against **false positives**) + 2 supporting questions (against **false negatives**, marked always ask).
98
+
99
+ See C.5.
100
+
101
+ ### Step 6: gate review
102
+
103
+ Run all 6 gates + all 13 items of the false-positive checklist.
104
+
105
+ ---
106
+
107
+ ## C.3 The six gates (all must pass before something is reported as a vulnerability)
108
+
109
+ | # | Gate | Criterion | Pass | Fail |
110
+ |---|---|---|---|---|
111
+ | 1 | **Process** | All stages completed with written evidence | Evidence at every stage | A stage lacks concrete evidence |
112
+ | 2 | **Reachability** | The attacker can reach and control the data in question | Clear evidence of an attacker-controlled path + PoC confirmation | Control or reachability cannot be shown |
113
+ | 3 | **Real Impact** | Exploitation leads to RCE, privilege escalation, or information disclosure | Direct impact in a concrete scenario | Only operational-robustness issues |
114
+ | 4 | **PoC Verification** | The PoC demonstrates the attack path | Shows control, triggering, and impact | The PoC fails to show the path or the impact |
115
+ | 5 | **Mathematical Boundary** | Mathematical analysis confirms the fragile condition can occur | Algebraic proof that the condition is possible | Mathematical proof that the check prevents it |
116
+ | 6 | **Environment** | No environmental defense can fully prevent exploitation | Defenses do not eliminate the vulnerability | An environmental defense fully blocks it |
117
+
118
+ ### Adjudication rules (fixed)
119
+
120
+ | Condition | Verdict |
121
+ |---|---|
122
+ | **All** 6 gates `pass` | `TRUE POSITIVE` |
123
+ | Any gate `fail`s | `FALSE POSITIVE` |
124
+ | No `fail`, but some `not_evaluated` | **`INCONCLUSIVE`** |
125
+
126
+ **Key rule**: if any stage's verification fails, **record the failure evidence and continue through the remaining stages**;
127
+ only when **all stages are complete** do you issue the `FALSE POSITIVE` verdict.
128
+
129
+ > `INCONCLUSIVE` is an outcome **added** by euthyna beyond Trail of Bits' original definition.
130
+ > Reason: the original implementation used the Stop hook to force continuation indefinitely until complete, while DSH's Stop hook
131
+ > **must rate-limit itself** (otherwise it loops forever) and cannot force indefinitely. See `docs/dsh-stop-gate.md`.
132
+
133
+ ### Adjudication format (evidence required)
134
+
135
+ ```
136
+ BUG #3 FALSE POSITIVE — integer underflow in packet_handler.c:142
137
+ Gate 5 (Mathematical Boundary) FAIL: line 98's check guarantees packet_size >= 16,
138
+ so (packet_size - header_size) >= 8. Underflow is mathematically impossible.
139
+
140
+ BUG #4 TRUE POSITIVE — command injection
141
+ All gates passed. Evidence: src/archive.js:42 (abc1234)
142
+ Reproduce: node tools/poc.js
143
+ Exploitability: EASY
144
+ Impact: arbitrary command execution as the service account
145
+ ```
146
+
147
+ **The format is machine-enforced**: after writing, validate with `euthyna gate <report file>` (see the "programmatic gate validation" section of SKILL.md). A TRUE POSITIVE that lacks evidence, lacks reproduction, or carries a FAIL gate is **downgraded to "observation"** by the validator and reported with exit code 10 — discipline does not depend on the adjudicator's self-awareness.
148
+
149
+ ---
150
+
151
+ ## C.4 The thirteen-item false-positive checklist (apply item by item to **every** suspected defect)
152
+
153
+ | # | Item | Question to ask |
154
+ |---|---|---|
155
+ | 1 | **Trace the full validation chain** | What are all the prior checks before the dangerous operation? Do not analyze isolated fragments |
156
+ | 1a | **Map the full conditional logic flow** | Is the seemingly unsafe `buffer[length-4]` only reachable when `length > 12`? |
157
+ | 2 | **Recognize defensive programming** | `ASSERT(size == expected)` is defense, not a vulnerability |
158
+ | 3 | **Confirm an exploitable data path** | Report only vulnerabilities with a **confirmed** exploitable data flow; do not assume network data reaches the dangerous function |
159
+ | 4 | **Understand the data source context** | API return values, compile-time constants, and network data carry different risk levels. Determine the true source |
160
+ | 5 | **Analyze the boundary-check logic** | If `size >= MIN` is checked and `MIN >= sizeof(header)`, the subtraction **cannot** underflow |
161
+ | 6 | **Verify the TOCTOU claim** | Can the checked value change between the check and the use? Checked then immediately used within the same function with no external modification = no TOCTOU |
162
+ | 7 | **Understand API contracts and trust boundaries** | Some APIs carry their own boundary protection and never write out of bounds regardless of input |
163
+ | 8 | **Distinguish internal storage from external input** | Config stores and registries are controlled by trusted components — they are **not** attacker-controlled |
164
+ | 9 | **Do not mistake pattern recognition for vulnerability analysis** | Code that "looks fragile" can be safe given the context and API contracts |
165
+ | 10 | **Verify concurrent access is actually possible** | Single-threaded initialization contexts cannot race; verify the threading model and synchronization mechanisms |
166
+ | 11 | **Assess real vs theoretical impact** | Failed storage of non-critical data is an operational issue. Ask: does it lead to code execution, privilege escalation, or information disclosure? |
167
+ | 12 | **Distinguish defense in depth from primary controls** | When the primary defense exists, a failing defense-in-depth layer is not necessarily a vulnerability |
168
+ | 13 | **Apply this checklist rigorously, not superficially** | Having a checklist does not stop false positives. **Every** suspected vulnerability must go through **all** items |
169
+
170
+ ---
171
+
172
+ ## C.5 Devil's advocate (two-way symmetric doubt)
173
+
174
+ This is the most elegant part of the whole design: **it prevents false positives and false negatives at the same time**.
175
+
176
+ ### Opposing the defect (11 questions, against false positives)
177
+
178
+ 1. Am I **hallucinating** this defect? (models are biased toward seeing bugs everywhere and rating them all critical)
179
+ 2. Am I doing **pattern matching** rather than analysis?
180
+ 3. Am I **confusing trust boundaries**?
181
+ 4. Is my proof **rigorous**? (any "probably" / "should"?)
182
+ 5. Am I treating **defense in depth** as a primary control?
183
+ 6. Does the attacker really **control** this input?
184
+ 7. Is this path really **reachable**?
185
+ 8. Am I **ignoring upstream validation**?
186
+ 9. Does the environmental defense **fully prevent** exploitation?
187
+ 10. Is the impact **real** or operational?
188
+ 11. Am I **overestimating severity**?
189
+
190
+ ### Supporting the defect (2 questions, **asked in every case**, against false negatives)
191
+
192
+ 12. **Am I dismissing a real defect because the exploitation path is complex or unlikely?**
193
+ 13. **Am I inventing mitigations or validation logic that I did not verify in the source code?**
194
+ → After reaching a conclusion, **re-read the code**.
195
+
196
+ > Questions 12 and 13 are the key to preventing false negatives. The model's default bias is "reporting too much",
197
+ > so most false-positive defenses suppress it; but over-suppression misses real defects.
198
+ > These two questions are the symmetric counterweight — they must not be skipped.
199
+
200
+ ---
201
+
202
+ ## C.6 Deep verification: task dependency structure
203
+
204
+ ```
205
+ Phase 1: 1.1 map trust boundaries + trace data flow
206
+ ├─ 1.2 research API contracts and security guarantees ┐
207
+ ├─ 1.3 environmental defense analysis ├─ all blocked by 1.1
208
+ └─ 1.4 cross-reference analysis ┘
209
+ Phase 2 (blocked by P1): 2.1 confirm attacker-controlled input ┐
210
+ 2.2 mathematical boundary verification ├─ parallel
211
+ 2.3 race-condition feasibility proof ┘
212
+ └→ 2.4 adversarial analysis (blocked by 2.1/2.2/2.3)
213
+ Phase 3 (blocked by P2): 3.1 prove real security impact ┐ parallel
214
+ 3.2 primary control vs defense in depth ┘
215
+ Phase 4 (blocked by P3): 4.1 pseudocode PoC + data-flow diagram (always required)
216
+ ├─ 4.2 executable PoC (if feasible) ┐
217
+ ├─ 4.3 unit-test PoC (if feasible) ├─ parallel
218
+ └─ 4.4 Negative PoC ┘
219
+ └→ 4.5 verify the PoC actually demonstrates the vulnerability
220
+ Phase 5 (blocked by P4): 5.1 devil's advocate review (13 questions)
221
+ Gate Review (blocked by P5): 6-gate assessment → verdict
222
+ ```
223
+
224
+ ### Execution rules
225
+
226
+ - Mark a task in-progress when it starts; mark it completed **only with concrete evidence**
227
+ - Launch parallel substages with concurrent subagents; **collect all results** before entering the next dependency gate
228
+ - **Never start a stage before all its dependencies are complete**
229
+ - **Phase 3 / Phase 5 / Gate Review must not be delegated** — they require cross-stage synthesis
230
+
231
+ ### Subagent permissions are deliberately asymmetric
232
+
233
+ | Subagent | Permission |
234
+ |---|---|
235
+ | Data-flow analysis | **read-only** |
236
+ | Exploitability verification | **read-only** |
237
+ | PoC construction | the only one with write access |
238
+
239
+ **The ability to manufacture evidence is concentrated in a single stage**; the earlier stages can only observe — this reduces the risk of contaminating evidence.
240
+
241
+ ---
242
+
243
+ ## C.7 PoC rules
244
+
245
+ ### Feasibility skip conditions (skipping requires a reason)
246
+
247
+ **Executable PoC**:
248
+
249
+ - Requires hardware or network unavailable locally
250
+ - The target language runtime is not installed
251
+ - Exploitation requires **modifying** production code (rather than calling it)
252
+ - The defect is in a closed-source component
253
+
254
+ **Unit-test PoC**:
255
+
256
+ - The project has no test infrastructure
257
+ - The fragile code cannot be invoked in isolation (deep dependency chain with no test fixtures)
258
+ - The build system is broken
259
+
260
+ ### The 5 PoC-verification questions
261
+
262
+ 1. Does the pseudocode accurately trace Step 1's data flow?
263
+ 2. Did the executable PoC **actually run** and show the impact? (capture **real output**, not expected output)
264
+ 3. Does the unit test pass and demonstrate the problem?
265
+ 4. Does the Negative PoC correctly identify the preconditions?
266
+ 5. **Is there any artificial bypass** (mocks, stubs, disabled checks)? — **if so, the PoC is invalid**
267
+
268
+ ### The purpose of the Negative PoC (not optional)
269
+
270
+ Shows the same path working normally under **benign input** → shows the **specific preconditions** exploitation requires →
271
+ explains why it does not hold under normal use, but the attacker can force it to hold.
272
+
273
+ **This is not proving the defect false** — it records the delta between the safe and unsafe conditions, which is useful for fixes.
274
+
275
+ ---
276
+
277
+ ## C.8 Batch triage
278
+
279
+ When there are multiple suspected bugs:
280
+
281
+ 1. Run step zero on **all** of them first (restatement often dismantles obvious false positives outright)
282
+ 2. Route each one independently
283
+ 3. **Process all standard-routed ones first, then deep-routed ones**
284
+ 4. After all verifications, check for **exploit chains** — findings that individually fail the gates may combine into a viable attack
285
+
286
+ ## C.9 Final summary format
287
+
288
+ 1. Count: X TRUE POSITIVE, Y FALSE POSITIVE, Z INCONCLUSIVE
289
+ 2. TRUE POSITIVE list: each with a brief vulnerability description
290
+ 3. FALSE POSITIVE list: each with a brief rejection reason
291
+ 4. INCONCLUSIVE list: **each with what is missing and why**
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: 代码安全审计:按 euthyna 纪律审一段代码、一次变更或一条漏洞结论,产出带证据的报告
3
+ argument-hint: "<路径 或 diff 范围>"
4
+ allowed-tools: Read, Grep, Glob, Bash, Task
5
+ ---
6
+
7
+ # /euthyna — 代码安全审计(判定纪律)
8
+
9
+ **审计目标:** $ARGUMENTS
10
+
11
+ 按 euthyna 技能执行一次完整审计:
12
+
13
+ 1. **先加载纪律**:找到 euthyna 技能目录(`~/.claude/skills/euthyna/`、项目 `.claude/skills/euthyna/` 或 `.agents/skills/euthyna/`),读 `SKILL.md`,需要时再读 `references/`。找不到就明说「技能缺失」,不要凭印象执行。
14
+ 2. **按入口决策树走**:单条漏洞结论 → 阶段 C;一次变更 → 阶段 B;依赖面 → 阶段 A;整体审计 → 阶段 B 为主。
15
+ 3. **先测量再读码**:diff 有删除行先跑 `history`;谈测试覆盖先跑 `coverage`;依赖声明先跑 `deps`(操作手册在 `references/fact-producers.md`)。
16
+ 4. **每条结论过六道门禁**:证据到 `文件:行号`、可复现命令、影响说明;拿不出证据的降级为「观察」。
17
+ 5. **三态裁定**:`BUG #N TRUE POSITIVE / FALSE POSITIVE / INCONCLUSIVE`。
18
+ 6. **报告落盘**:`<项目>_EUTHYNA_AUDIT_<日期>.md`,并跑 `euthyna gate <报告>` 校验(退出码 0 才算过)。
@@ -0,0 +1,8 @@
1
+ ---
2
+ description: Run the euthyna code security audit CLI
3
+ ---
4
+ Run the euthyna CLI with these arguments and report the measured result:
5
+
6
+ euthyna $ARGUMENTS
7
+
8
+ If `euthyna` is not installed, use `npx -y euthyna $ARGUMENTS` instead. Quote the command's output verbatim, exit code included — never estimate or re-derive numbers. If the euthyna skill is installed (`.agents/skills/euthyna/` or `~/.agents/skills/euthyna/`), read its SKILL.md and interpret the output under the six-gate adjudication format; claims without evidence are downgraded to observations.
package/README.md CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  <p align="center">
12
12
  <a href="https://github.com/slow-stack/euthyna/actions/workflows/ci.yml"><img src="https://github.com/slow-stack/euthyna/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
13
+ <a href="https://www.skills.sh/slow-stack/euthyna"><img src="https://skills.sh/b/slow-stack/euthyna.svg" alt="Agent skills installs"></a>
14
+ <a href="https://awesome-dsh-plugin.com/p/slow-stack/euthyna/"><img src="https://img.shields.io/badge/DSH%20plugin-listed-blue" alt="Listed in the awesome-dsh-plugin catalog"></a>
13
15
  </p>
14
16
 
15
17
  **euthyna is a code security audit framework for AI coding agents.** It is not another
@@ -93,13 +95,19 @@ the project is deliberately zero-dependency.
93
95
 
94
96
  | Host | The skill (audit discipline) | The CLI (fact producers) |
95
97
  |---|---|---|
96
- | **DSH** | Copy `.agents/skills/euthyna/` into `~/.agents/skills/` (user-wide) or `<project>/.agents/skills/`. Markdown hot-reloads; no restart needed. | `npm install -g euthyna` — runs in any terminal |
97
- | **Claude Code** | Copy the same folder into `~/.claude/skills/` | Same |
98
+ | **DSH** | `dsh plugin --profile web add euthyna` — the npm package mounts its own skill; or copy `.agents/skills/euthyna/` into `~/.agents/skills/` (user-wide) or `<project>/.agents/skills/`. Markdown hot-reloads; no restart needed. | `npm install -g euthyna` — runs in any terminal |
99
+ | **Claude Code** | `/plugin marketplace add slow-stack/euthyna` then `/plugin install euthyna@euthyna`, or copy `.agents/skills/euthyna/` into `~/.claude/skills/` | Same |
98
100
  | **Codex** | The same Markdown layer works; packaging goes through Codex's plugin/marketplace format | Same |
99
- | **Hermes** | Copy the same folder into `~/.hermes/skills/` under a category folder (Hermes reads the open skill standard; or install from a repo with `hermes skills install`) | Same |
100
- | **OpenCode** | Copy the same folder into `~/.agents/skills/` or `~/.config/opencode/skills/` (OpenCode loads both; unknown frontmatter fields are ignored) | Same |
101
+ | **Hermes** | Copy the same folder into `~/.hermes/skills/` under a category folder, or install from a repo with `hermes skills install` — and for the slash command, install the repo as a plugin (see below) | Same |
102
+ | **OpenCode** | Copy the same folder into `~/.agents/skills/` or `~/.config/opencode/skills/` (OpenCode loads both; unknown frontmatter fields are ignored). For a `/euthyna` slash command, copy `.opencode/commands/euthyna.md` into `~/.config/opencode/commands/` — it is a prompt template that tells the model to run the CLI | Same |
103
+ | **OpenClaw** | Copy the same folder into `~/.agents/skills/` (or `<workspace>/.agents/skills/`) — OpenClaw exposes every `user-invocable` skill as a slash command natively, so `/euthyna` works with no extra file | Same |
101
104
  | **Any terminal** | — | `npm install -g euthyna`, then `euthyna …` |
102
105
 
106
+ The skill ships in two languages. The directory above is the Chinese original (`euthyna`);
107
+ an English mirror lives at `.agents/skills/euthyna-en/` (skill name `euthyna-en`) — install
108
+ that one for an English-speaking agent, or translate the folder yourself. Both define the
109
+ same discipline, and `euthyna gate` accepts report markers in either language.
110
+
103
111
  Two honest notes:
104
112
 
105
113
  - **The skill is the instructions; the CLI is the measurement.** The skill directory
@@ -107,9 +115,47 @@ Two honest notes:
107
115
  keep this repository checked out; on a host without the CLI, the skill requires the
108
116
  unmeasurable criteria to be recorded as *not evaluated* rather than guessed at — that
109
117
  fallback is the design, not a gap.
110
- - **The skill text and the CLI's reports are currently written in Chinese.** The
111
- discipline is host-agnostic Markdown, but an English reader should expect Chinese
112
- output from the tool itself.
118
+ - **The CLI speaks Chinese by default, English on request.** Output is Chinese unless you
119
+ pass `--lang en` (any command) or set `EUTHYNA_LANG=en`; the default never changes for
120
+ existing users. The skill text and the CLI's reports exist in both languages — the
121
+ English reader should expect Chinese only from a run that did not ask for English.
122
+
123
+ ---
124
+
125
+ ## 🎯 First use
126
+
127
+ euthyna is **user-invoked, not auto-triggering**. The skill declares
128
+ `disable-model-invocation: true`, so the model will not load it on its own —
129
+ you have to ask for the audit explicitly. That is also how you tell it apart
130
+ from other security skills you may have installed: **if you did not name it,
131
+ it did not run.**
132
+
133
+ ### Triggering the audit
134
+
135
+ Say it plainly in conversation:
136
+
137
+ > 「用 euthyna 审计一下 `D:\some-project`,审完再交付」
138
+
139
+ The agent then loads the skill and runs the audit discipline: it produces the
140
+ deterministic facts (`history` / `coverage` / `deps`) first, walks every
141
+ suspect through the six gates, and writes a report file instead of only
142
+ replying in chat.
143
+
144
+ ### Slash commands
145
+
146
+ | Host | Command | Setup |
147
+ |---|---|---|
148
+ | Claude Code | `/euthyna <path>` | copy `.claude/commands/euthyna.md` from the package into `~/.claude/commands/` (user-wide) or `.claude/commands/` (project) |
149
+ | Codex | — | Codex's custom-prompt slash commands (`~/.codex/prompts/`) are deprecated upstream; the same Markdown can still be placed there manually |
150
+ | DSH | `/euthyna` | installed with the plugin; after a restart the command prints the usage manual (DSH slash commands run without reaching the model) |
151
+ | Hermes | `/euthyna <subcommand> <args…>` | install this repository as a Hermes plugin: `hermes plugins install slow-stack/euthyna` then `hermes plugins enable euthyna` (needs Node >= 20 on PATH; the repo root carries `plugin.yaml` + `__init__.py`). The command forwards to the CLI and prints its output without reaching the model. The skill itself can still be installed separately with `hermes skills install slow-stack/euthyna/.agents/skills/euthyna` |
152
+
153
+ ### How to tell it was euthyna that audited
154
+
155
+ - the report filename is `<PROJECT>_EUTHYNA_AUDIT_<YYYY-MM-DD>.md`
156
+ - verdicts use the three-state shape `BUG #N TRUE POSITIVE / FALSE POSITIVE / INCONCLUSIVE`
157
+ - every claim cites `path:L123` evidence and a reproduce command
158
+ - missing data is recorded as *not evaluated*, never as "clean"
113
159
 
114
160
  ---
115
161
 
@@ -258,6 +304,7 @@ This project tries to be explicit about the difference. Current state:
258
304
  euthyna/
259
305
  ├── bin/ src/ test/ Fact producers (zero dependencies, Node >= 20)
260
306
  ├── .agents/skills/euthyna/ The audit discipline, as a portable skill
307
+ ├── plugin.yaml __init__.py Hermes plugin: the /euthyna slash command
261
308
  ├── bench/ Blind recall benchmark + results
262
309
  ├── docs/ Design notes and case studies (English and Chinese)
263
310
  ├── tools/ Research and verification scripts