@vigolium/piolium 0.0.1

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.
Files changed (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/agents/access-auditor.md +300 -0
  4. package/agents/assumption-breaker.md +154 -0
  5. package/agents/attack-designer.md +116 -0
  6. package/agents/code-scanner.md +139 -0
  7. package/agents/concurrency-auditor.md +238 -0
  8. package/agents/confirm-writer.md +257 -0
  9. package/agents/context-reviewer.md +274 -0
  10. package/agents/cross-verifier.md +165 -0
  11. package/agents/cve-scout.md +381 -0
  12. package/agents/env-builder.md +282 -0
  13. package/agents/env-profiler.md +205 -0
  14. package/agents/evidence-collector.md +140 -0
  15. package/agents/finding-grader.md +142 -0
  16. package/agents/finding-writer.md +148 -0
  17. package/agents/flow-tracer.md +106 -0
  18. package/agents/goal-backtracer.md +146 -0
  19. package/agents/history-miner.md +467 -0
  20. package/agents/independent-verifier.md +118 -0
  21. package/agents/intent-mapper.md +183 -0
  22. package/agents/longshot-collector.md +128 -0
  23. package/agents/longshot-prober.md +126 -0
  24. package/agents/patch-auditor.md +73 -0
  25. package/agents/poc-author.md +124 -0
  26. package/agents/poc-runner.md +194 -0
  27. package/agents/probe-lead.md +269 -0
  28. package/agents/red-challenger.md +101 -0
  29. package/agents/report-composer.md +208 -0
  30. package/agents/review-adjudicator.md +216 -0
  31. package/agents/spec-auditor.md +155 -0
  32. package/agents/taint-tracer.md +265 -0
  33. package/agents/test-locator.md +209 -0
  34. package/agents/threat-modeler.md +132 -0
  35. package/agents/variant-scanner.md +108 -0
  36. package/agents/variant-spotter.md +110 -0
  37. package/bin/piolium.mjs +376 -0
  38. package/extensions/piolium/_vendor/yaml.bundle.d.mts +6 -0
  39. package/extensions/piolium/_vendor/yaml.bundle.mjs +139 -0
  40. package/extensions/piolium/agent-runner.ts +322 -0
  41. package/extensions/piolium/agents.ts +266 -0
  42. package/extensions/piolium/audit-state.ts +522 -0
  43. package/extensions/piolium/bundled-resources.ts +97 -0
  44. package/extensions/piolium/candidate-scan.ts +966 -0
  45. package/extensions/piolium/command-target.ts +177 -0
  46. package/extensions/piolium/console-stream.ts +57 -0
  47. package/extensions/piolium/export-results.ts +380 -0
  48. package/extensions/piolium/findings.ts +448 -0
  49. package/extensions/piolium/heartbeat.ts +182 -0
  50. package/extensions/piolium/help.ts +234 -0
  51. package/extensions/piolium/index.ts +1865 -0
  52. package/extensions/piolium/longshot.ts +530 -0
  53. package/extensions/piolium/matcher-suggestions.ts +196 -0
  54. package/extensions/piolium/matcher-utils.ts +83 -0
  55. package/extensions/piolium/modes/balanced.ts +750 -0
  56. package/extensions/piolium/modes/confirm-bootstrap.ts +186 -0
  57. package/extensions/piolium/modes/confirm.ts +697 -0
  58. package/extensions/piolium/modes/deep.ts +917 -0
  59. package/extensions/piolium/modes/diff.ts +177 -0
  60. package/extensions/piolium/modes/lite.ts +540 -0
  61. package/extensions/piolium/modes/longshot.ts +595 -0
  62. package/extensions/piolium/modes/merge.ts +204 -0
  63. package/extensions/piolium/modes/phase-runner.ts +267 -0
  64. package/extensions/piolium/modes/reinvest.ts +546 -0
  65. package/extensions/piolium/modes/revisit.ts +279 -0
  66. package/extensions/piolium/modes.ts +48 -0
  67. package/extensions/piolium/phase-labels.ts +123 -0
  68. package/extensions/piolium/phase-status-strip.ts +92 -0
  69. package/extensions/piolium/prompt-prefix-editor.ts +39 -0
  70. package/extensions/piolium/providers/anthropic-vertex.ts +836 -0
  71. package/extensions/piolium/recon.ts +409 -0
  72. package/extensions/piolium/result-stats.ts +105 -0
  73. package/extensions/piolium/retry.ts +120 -0
  74. package/extensions/piolium/scheduler.ts +212 -0
  75. package/extensions/piolium/secrets.ts +368 -0
  76. package/extensions/piolium/tools/web-tools.ts +148 -0
  77. package/package.json +77 -0
  78. package/skills/agentic-actions-auditor/SKILL.md +327 -0
  79. package/skills/agentic-actions-auditor/references/action-profiles.md +186 -0
  80. package/skills/agentic-actions-auditor/references/cross-file-resolution.md +209 -0
  81. package/skills/agentic-actions-auditor/references/foundations.md +94 -0
  82. package/skills/agentic-actions-auditor/references/vector-a-env-var-intermediary.md +77 -0
  83. package/skills/agentic-actions-auditor/references/vector-b-direct-expression-injection.md +83 -0
  84. package/skills/agentic-actions-auditor/references/vector-c-cli-data-fetch.md +83 -0
  85. package/skills/agentic-actions-auditor/references/vector-d-pr-target-checkout.md +88 -0
  86. package/skills/agentic-actions-auditor/references/vector-e-error-log-injection.md +88 -0
  87. package/skills/agentic-actions-auditor/references/vector-f-subshell-expansion.md +82 -0
  88. package/skills/agentic-actions-auditor/references/vector-g-eval-of-ai-output.md +91 -0
  89. package/skills/agentic-actions-auditor/references/vector-h-dangerous-sandbox-configs.md +102 -0
  90. package/skills/agentic-actions-auditor/references/vector-i-wildcard-allowlists.md +88 -0
  91. package/skills/audit/SKILL.md +562 -0
  92. package/skills/audit/assets/icon.svg +7 -0
  93. package/skills/audit/hooks/scripts/validate_phase_output.py +550 -0
  94. package/skills/audit/references/adversarial-review.md +148 -0
  95. package/skills/audit/references/architecture-aware-sast.md +306 -0
  96. package/skills/audit/references/audit-workflow.md +737 -0
  97. package/skills/audit/references/chamber-protocol.md +384 -0
  98. package/skills/audit/references/creative-attack-modes.md +221 -0
  99. package/skills/audit/references/deep-analysis.md +273 -0
  100. package/skills/audit/references/domain-attack-playbooks.md +1129 -0
  101. package/skills/audit/references/knowledge-base-template.md +513 -0
  102. package/skills/audit/references/real-env-validation.md +191 -0
  103. package/skills/audit/references/report-templates.md +417 -0
  104. package/skills/audit/references/triage-and-prereqs.md +134 -0
  105. package/skills/audit/scripts/consolidate_drafts.py +554 -0
  106. package/skills/audit/scripts/partition_findings.py +152 -0
  107. package/skills/audit/scripts/rg-hotspots.sh +121 -0
  108. package/skills/audit/scripts/stamp_file_state.py +349 -0
  109. package/skills/code-reviewer/SKILL.md +65 -0
  110. package/skills/codeql/SKILL.md +281 -0
  111. package/skills/codeql/references/build-fixes.md +90 -0
  112. package/skills/codeql/references/diagnostic-query-templates.md +339 -0
  113. package/skills/codeql/references/extension-yaml-format.md +209 -0
  114. package/skills/codeql/references/important-only-suite.md +153 -0
  115. package/skills/codeql/references/language-details.md +207 -0
  116. package/skills/codeql/references/macos-arm64e-workaround.md +179 -0
  117. package/skills/codeql/references/performance-tuning.md +111 -0
  118. package/skills/codeql/references/quality-assessment.md +172 -0
  119. package/skills/codeql/references/ruleset-catalog.md +63 -0
  120. package/skills/codeql/references/run-all-suite.md +92 -0
  121. package/skills/codeql/references/sarif-processing.md +79 -0
  122. package/skills/codeql/references/threat-models.md +51 -0
  123. package/skills/codeql/workflows/build-database.md +280 -0
  124. package/skills/codeql/workflows/create-data-extensions.md +261 -0
  125. package/skills/codeql/workflows/run-analysis.md +301 -0
  126. package/skills/differential-review/SKILL.md +220 -0
  127. package/skills/differential-review/adversarial.md +203 -0
  128. package/skills/differential-review/methodology.md +234 -0
  129. package/skills/differential-review/patterns.md +300 -0
  130. package/skills/differential-review/reporting.md +369 -0
  131. package/skills/fp-check/SKILL.md +125 -0
  132. package/skills/fp-check/references/bug-class-verification.md +114 -0
  133. package/skills/fp-check/references/deep-verification.md +143 -0
  134. package/skills/fp-check/references/evidence-templates.md +91 -0
  135. package/skills/fp-check/references/false-positive-patterns.md +115 -0
  136. package/skills/fp-check/references/gate-reviews.md +27 -0
  137. package/skills/fp-check/references/standard-verification.md +78 -0
  138. package/skills/insecure-defaults/SKILL.md +117 -0
  139. package/skills/insecure-defaults/references/examples.md +409 -0
  140. package/skills/last30days/SKILL.md +444 -0
  141. package/skills/sarif-parsing/SKILL.md +483 -0
  142. package/skills/sarif-parsing/resources/jq-queries.md +162 -0
  143. package/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
  144. package/skills/security-threat-model/LICENSE.txt +201 -0
  145. package/skills/security-threat-model/SKILL.md +81 -0
  146. package/skills/security-threat-model/agents/openai.yaml +4 -0
  147. package/skills/security-threat-model/references/prompt-template.md +255 -0
  148. package/skills/security-threat-model/references/security-controls-and-assets.md +32 -0
  149. package/skills/semgrep/SKILL.md +212 -0
  150. package/skills/semgrep/references/rulesets.md +162 -0
  151. package/skills/semgrep/references/scan-modes.md +110 -0
  152. package/skills/semgrep/references/scanner-task-prompt.md +140 -0
  153. package/skills/semgrep/scripts/merge_sarif.py +203 -0
  154. package/skills/semgrep/workflows/scan-workflow.md +311 -0
  155. package/skills/semgrep-rule-creator/SKILL.md +168 -0
  156. package/skills/semgrep-rule-creator/references/quick-reference.md +202 -0
  157. package/skills/semgrep-rule-creator/references/workflow.md +240 -0
  158. package/skills/semgrep-rule-variant-creator/SKILL.md +205 -0
  159. package/skills/semgrep-rule-variant-creator/references/applicability-analysis.md +250 -0
  160. package/skills/semgrep-rule-variant-creator/references/language-syntax-guide.md +324 -0
  161. package/skills/semgrep-rule-variant-creator/references/workflow.md +518 -0
  162. package/skills/sharp-edges/SKILL.md +292 -0
  163. package/skills/sharp-edges/references/auth-patterns.md +252 -0
  164. package/skills/sharp-edges/references/case-studies.md +274 -0
  165. package/skills/sharp-edges/references/config-patterns.md +333 -0
  166. package/skills/sharp-edges/references/crypto-apis.md +190 -0
  167. package/skills/sharp-edges/references/lang-c.md +205 -0
  168. package/skills/sharp-edges/references/lang-csharp.md +285 -0
  169. package/skills/sharp-edges/references/lang-go.md +270 -0
  170. package/skills/sharp-edges/references/lang-java.md +263 -0
  171. package/skills/sharp-edges/references/lang-javascript.md +269 -0
  172. package/skills/sharp-edges/references/lang-kotlin.md +265 -0
  173. package/skills/sharp-edges/references/lang-php.md +245 -0
  174. package/skills/sharp-edges/references/lang-python.md +274 -0
  175. package/skills/sharp-edges/references/lang-ruby.md +273 -0
  176. package/skills/sharp-edges/references/lang-rust.md +272 -0
  177. package/skills/sharp-edges/references/lang-swift.md +287 -0
  178. package/skills/sharp-edges/references/language-specific.md +588 -0
  179. package/skills/spec-to-code-compliance/SKILL.md +357 -0
  180. package/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +69 -0
  181. package/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +417 -0
  182. package/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +105 -0
  183. package/skills/supply-chain-risk-auditor/SKILL.md +67 -0
  184. package/skills/supply-chain-risk-auditor/resources/results-template.md +41 -0
  185. package/skills/variant-analysis/METHODOLOGY.md +327 -0
  186. package/skills/variant-analysis/SKILL.md +142 -0
  187. package/skills/variant-analysis/resources/codeql/cpp.ql +119 -0
  188. package/skills/variant-analysis/resources/codeql/go.ql +69 -0
  189. package/skills/variant-analysis/resources/codeql/java.ql +71 -0
  190. package/skills/variant-analysis/resources/codeql/javascript.ql +63 -0
  191. package/skills/variant-analysis/resources/codeql/python.ql +80 -0
  192. package/skills/variant-analysis/resources/semgrep/cpp.yaml +98 -0
  193. package/skills/variant-analysis/resources/semgrep/go.yaml +63 -0
  194. package/skills/variant-analysis/resources/semgrep/java.yaml +61 -0
  195. package/skills/variant-analysis/resources/semgrep/javascript.yaml +60 -0
  196. package/skills/variant-analysis/resources/semgrep/python.yaml +72 -0
  197. package/skills/variant-analysis/resources/variant-report-template.md +75 -0
  198. package/skills/vuln-report/SKILL.md +137 -0
  199. package/skills/vuln-report/agents/openai.yaml +4 -0
  200. package/skills/vuln-report/references/report-template.md +135 -0
  201. package/skills/wooyun-legacy/SKILL.md +367 -0
  202. package/skills/wooyun-legacy/references/bank-penetration.md +222 -0
  203. package/skills/wooyun-legacy/references/checklists/command-execution-checklist.md +119 -0
  204. package/skills/wooyun-legacy/references/checklists/csrf-checklist.md +74 -0
  205. package/skills/wooyun-legacy/references/checklists/file-upload-checklist.md +108 -0
  206. package/skills/wooyun-legacy/references/checklists/info-disclosure-checklist.md +114 -0
  207. package/skills/wooyun-legacy/references/checklists/logic-flaws-checklist.md +95 -0
  208. package/skills/wooyun-legacy/references/checklists/misconfig-checklist.md +124 -0
  209. package/skills/wooyun-legacy/references/checklists/path-traversal-checklist.md +87 -0
  210. package/skills/wooyun-legacy/references/checklists/rce-checklist.md +93 -0
  211. package/skills/wooyun-legacy/references/checklists/sql-injection-checklist.md +97 -0
  212. package/skills/wooyun-legacy/references/checklists/ssrf-checklist.md +99 -0
  213. package/skills/wooyun-legacy/references/checklists/unauthorized-access-checklist.md +89 -0
  214. package/skills/wooyun-legacy/references/checklists/weak-password-checklist.md +115 -0
  215. package/skills/wooyun-legacy/references/checklists/xss-checklist.md +103 -0
  216. package/skills/wooyun-legacy/references/checklists/xxe-checklist.md +130 -0
  217. package/skills/wooyun-legacy/references/info-disclosure.md +975 -0
  218. package/skills/wooyun-legacy/references/logic-flaws.md +721 -0
  219. package/skills/wooyun-legacy/references/path-traversal.md +1191 -0
  220. package/skills/wooyun-legacy/references/telecom-penetration.md +156 -0
  221. package/skills/wooyun-legacy/references/unauthorized-access.md +980 -0
  222. package/skills/wooyun-legacy/references/xss.md +746 -0
  223. package/skills/zeroize-audit/SKILL.md +371 -0
  224. package/skills/zeroize-audit/configs/c.yaml +21 -0
  225. package/skills/zeroize-audit/configs/default.yaml +128 -0
  226. package/skills/zeroize-audit/configs/rust.yaml +83 -0
  227. package/skills/zeroize-audit/prompts/report_template.md +238 -0
  228. package/skills/zeroize-audit/prompts/system.md +163 -0
  229. package/skills/zeroize-audit/prompts/task.md +97 -0
  230. package/skills/zeroize-audit/references/compile-commands.md +231 -0
  231. package/skills/zeroize-audit/references/detection-strategy.md +191 -0
  232. package/skills/zeroize-audit/references/ir-analysis.md +252 -0
  233. package/skills/zeroize-audit/references/mcp-analysis.md +221 -0
  234. package/skills/zeroize-audit/references/poc-generation.md +470 -0
  235. package/skills/zeroize-audit/references/rust-zeroization-patterns.md +867 -0
  236. package/skills/zeroize-audit/schemas/input.json +83 -0
  237. package/skills/zeroize-audit/schemas/output.json +140 -0
  238. package/skills/zeroize-audit/tools/analyze_asm.sh +202 -0
  239. package/skills/zeroize-audit/tools/analyze_cfg.py +381 -0
  240. package/skills/zeroize-audit/tools/analyze_heap.sh +211 -0
  241. package/skills/zeroize-audit/tools/analyze_ir_semantic.py +429 -0
  242. package/skills/zeroize-audit/tools/diff_ir.sh +135 -0
  243. package/skills/zeroize-audit/tools/diff_rust_mir.sh +189 -0
  244. package/skills/zeroize-audit/tools/emit_asm.sh +67 -0
  245. package/skills/zeroize-audit/tools/emit_ir.sh +77 -0
  246. package/skills/zeroize-audit/tools/emit_rust_asm.sh +178 -0
  247. package/skills/zeroize-audit/tools/emit_rust_ir.sh +150 -0
  248. package/skills/zeroize-audit/tools/emit_rust_mir.sh +158 -0
  249. package/skills/zeroize-audit/tools/extract_compile_flags.py +284 -0
  250. package/skills/zeroize-audit/tools/generate_poc.py +1329 -0
  251. package/skills/zeroize-audit/tools/mcp/apply_confidence_gates.py +113 -0
  252. package/skills/zeroize-audit/tools/mcp/check_mcp.sh +68 -0
  253. package/skills/zeroize-audit/tools/mcp/normalize_mcp_evidence.py +125 -0
  254. package/skills/zeroize-audit/tools/scripts/check_llvm_patterns.py +481 -0
  255. package/skills/zeroize-audit/tools/scripts/check_mir_patterns.py +554 -0
  256. package/skills/zeroize-audit/tools/scripts/check_rust_asm.py +424 -0
  257. package/skills/zeroize-audit/tools/scripts/check_rust_asm_aarch64.py +300 -0
  258. package/skills/zeroize-audit/tools/scripts/check_rust_asm_x86.py +283 -0
  259. package/skills/zeroize-audit/tools/scripts/find_dangerous_apis.py +375 -0
  260. package/skills/zeroize-audit/tools/scripts/semantic_audit.py +923 -0
  261. package/skills/zeroize-audit/tools/track_dataflow.sh +196 -0
  262. package/skills/zeroize-audit/tools/validate_rust_toolchain.sh +298 -0
  263. package/skills/zeroize-audit/workflows/phase-0-preflight.md +150 -0
  264. package/skills/zeroize-audit/workflows/phase-1-source-analysis.md +144 -0
  265. package/skills/zeroize-audit/workflows/phase-2-compiler-analysis.md +139 -0
  266. package/skills/zeroize-audit/workflows/phase-3-interim-report.md +46 -0
  267. package/skills/zeroize-audit/workflows/phase-4-poc-generation.md +46 -0
  268. package/skills/zeroize-audit/workflows/phase-5-poc-validation.md +136 -0
  269. package/skills/zeroize-audit/workflows/phase-6-final-report.md +44 -0
  270. package/skills/zeroize-audit/workflows/phase-7-test-generation.md +42 -0
  271. package/themes/piolium-srcery.json +94 -0
@@ -0,0 +1,221 @@
1
+ # MCP-Assisted Semantic Analysis
2
+
3
+ This reference covers how to configure, query, and interpret Serena MCP evidence during the zeroize-audit semantic pass. For compile DB generation and flag extraction, refer to the compile-commands reference (loaded separately from SKILL.md).
4
+
5
+ ---
6
+
7
+ ## Preconditions
8
+
9
+ Before running any MCP queries, the following must hold. These are verified during Step 1 (Preflight) in `task.md` — do not re-run preflight here, just confirm the relevant outputs:
10
+
11
+ | Precondition | Failure behavior |
12
+ |---|---|
13
+ | `compile_commands.json` valid and readable | Do not run MCP queries; fail the run if `mcp_mode=require` |
14
+ | Codebase buildable from compile DB commands | Same as above |
15
+ | `check_mcp.sh` exits 0 | If `mcp_mode=require`: stop run. If `mcp_mode=prefer`: set `mcp_available=false`, continue without MCP, apply confidence downgrades |
16
+ | Serena can resolve at least one symbol in the TU | Log a warning; proceed but mark findings from that TU as `needs_review` |
17
+
18
+ **Rust note**: Cargo does not natively produce `compile_commands.json`. Use `bear -- cargo build` or `bear -- cargo check` to generate it. `rust-project.json` is not a substitute in this workflow.
19
+
20
+ ---
21
+
22
+ ## Configuring Serena
23
+
24
+ The `plugin.json` registers Serena as the `serena` MCP server, launched via `uvx`. Serena wraps language servers (clangd for C/C++) and exposes semantic analysis as high-level MCP tools. It auto-discovers `compile_commands.json` from the project working directory.
25
+
26
+ **Prerequisites:**
27
+ - `uvx` must be on PATH (installed with `uv` — see https://docs.astral.sh/uv/)
28
+ - Serena is fetched and run automatically via `uvx --from git+https://github.com/oraios/serena`
29
+ - No separate `clangd` installation is required — Serena manages language server dependencies internally
30
+
31
+ **Verify before querying:**
32
+
33
+ ```bash
34
+ {baseDir}/tools/mcp/check_mcp.sh \
35
+ --compile-db /path/to/compile_commands.json
36
+ ```
37
+
38
+ A non-zero exit means MCP is unreachable. Apply the preflight failure behavior above.
39
+
40
+ ---
41
+
42
+ ## MCP Tool Reference
43
+
44
+ Serena abstracts LSP methods into higher-level, symbol-name-based tools. Unlike raw LSP, you query by symbol name rather than file position.
45
+
46
+ | MCP tool name | Purpose in zeroize-audit | Key parameters |
47
+ |---|---|---|
48
+ | `activate_project` | **Must be called first.** Activates the project so Serena indexes it | `project` (path to repo root) |
49
+ | `find_symbol` | Resolve where a sensitive symbol is defined; get type info, body, and struct layout | `symbol_name`, `file_path` (optional), `include_body`, `depth` |
50
+ | `find_referencing_symbols` | Find all use sites and callers across files | `symbol_name`, `file_path` (optional) |
51
+ | `get_symbols_overview` | List all symbols in a file — useful for exploring unfamiliar TUs | `file_path` |
52
+
53
+ **Mapping from previous LSP-based queries:**
54
+
55
+ | Analysis need | Serena tool | Notes |
56
+ |---|---|---|
57
+ | Resolve definition | `find_symbol` | Search by name; returns file, line, kind, and optionally body |
58
+ | Find all references | `find_referencing_symbols` | Returns referencing symbols with file and line |
59
+ | Find callers (incoming calls) | `find_referencing_symbols` | Search for references to a function name |
60
+ | Find callees (outgoing calls) | `find_symbol` + source read | Get function body via `include_body: true`, then resolve called symbols |
61
+ | Resolve type / hover | `find_symbol` with `include_body: true` | Type information is included in the symbol result |
62
+ | Follow typedef chain | `find_symbol` | Look up the type name directly |
63
+
64
+ ---
65
+
66
+ ## Query Order
67
+
68
+ Run queries in this order so each step's output informs the next. All queries for a given TU should complete before moving to the next TU.
69
+
70
+ ### Step 0 — Activate the project (`activate_project`)
71
+
72
+ This **must** be called once before any other Serena tool. Pass the repository root path. If activation fails, treat MCP as unavailable.
73
+
74
+ ```
75
+ Tool: activate_project
76
+ Arguments:
77
+ project: "/path/to/repo"
78
+ ```
79
+
80
+ Expected: confirmation that the project is active. Serena will start indexing the codebase (including launching clangd if needed). Wait for activation to succeed before proceeding.
81
+
82
+ ### Step 1 — Resolve symbol definition (`find_symbol`)
83
+
84
+ Establishes the canonical declaration location and type information used in all subsequent queries.
85
+
86
+ ```
87
+ Tool: find_symbol
88
+ Arguments:
89
+ symbol_name: "secret_key"
90
+ include_body: true
91
+ ```
92
+
93
+ Expected: result with `file`, `line`, `kind`, `symbol` name, and body content. The body provides type information (array sizes, struct layout) needed for wipe-size validation in Step 3. Store this as the canonical location for Steps 2–4.
94
+
95
+ If the symbol name is ambiguous, narrow with `file_path`:
96
+
97
+ ```
98
+ Tool: find_symbol
99
+ Arguments:
100
+ symbol_name: "secret_key"
101
+ file_path: "src/crypto.c"
102
+ include_body: true
103
+ ```
104
+
105
+ ### Step 2 — Collect all use sites (`find_referencing_symbols`)
106
+
107
+ Finds every location where the sensitive symbol is referenced. Use these to locate adjacent wipe calls and detect copies to other scopes.
108
+
109
+ ```
110
+ Tool: find_referencing_symbols
111
+ Arguments:
112
+ symbol_name: "secret_key"
113
+ ```
114
+
115
+ Expected: list of referencing symbols with `file`, `line`, `symbol`, and `kind`. For each reference in a file other than the source TU, check that file for cleanup. References in generated files (build directory) can be filtered by source directory prefix.
116
+
117
+ ### Step 3 — Resolve type and size
118
+
119
+ Type information is returned as part of `find_symbol` results (Step 1). If you need to resolve a typedef or follow a type alias chain, look up the type name directly:
120
+
121
+ ```
122
+ Tool: find_symbol
123
+ Arguments:
124
+ symbol_name: "secret_key_t"
125
+ include_body: true
126
+ ```
127
+
128
+ Use this to validate wipe sizes — a `sizeof(ptr)` bug will be apparent when the symbol body reveals `uint8_t [32]` but the wipe uses `sizeof(uint8_t *)`.
129
+
130
+ ### Step 4 — Trace callers and cleanup paths
131
+
132
+ Use `find_referencing_symbols` on the function containing the sensitive object to find callers that may hold their own copy of the secret. Use it on wipe wrapper functions to find cleanup paths.
133
+
134
+ ```
135
+ Tool: find_referencing_symbols
136
+ Arguments:
137
+ symbol_name: "process_key"
138
+ ```
139
+
140
+ For outgoing calls (what does this function call?), read the function body from `find_symbol` output and resolve each called function:
141
+
142
+ ```
143
+ Tool: find_symbol
144
+ Arguments:
145
+ symbol_name: "process_key"
146
+ include_body: true
147
+ ```
148
+
149
+ Then for each function called within the body:
150
+
151
+ ```
152
+ Tool: find_symbol
153
+ Arguments:
154
+ symbol_name: "cleanup_secret"
155
+ ```
156
+
157
+ ### Step 5 — Normalize output
158
+
159
+ Before using any MCP results in confidence scoring or finding emission, normalize:
160
+
161
+ ```bash
162
+ python {baseDir}/tools/mcp/normalize_mcp_evidence.py \
163
+ --input /tmp/raw_mcp_results.json \
164
+ --output /tmp/normalized_mcp_results.json
165
+ ```
166
+
167
+ The normalizer produces a consistent schema consumed by the MCP semantic pass and subsequent confidence gating steps.
168
+
169
+ ---
170
+
171
+ ## Interpreting Responses
172
+
173
+ | Response | Meaning | Action |
174
+ |---|---|---|
175
+ | Empty results | Serena could not resolve the symbol | Check compile DB path; verify symbol name spelling; retry with `file_path` to narrow scope |
176
+ | Timeout (> `mcp_timeout_ms`) | Query too slow | Mark finding as `needs_review`; do not wait indefinitely |
177
+ | Multiple results for same name | Symbol is defined in multiple TUs or headers | Use `file_path` to disambiguate; note in evidence |
178
+ | References in generated files | Hits in build-generated sources | Filter by source directory prefix |
179
+ | No referencing symbols found | Symbol is unused or not indexed | Acceptable for leaf functions; note in evidence |
180
+
181
+ ---
182
+
183
+ ## Confidence Scoring
184
+
185
+ MCP evidence contributes one signal toward the 2-signal threshold for `confirmed` findings (see SKILL.md Confidence Gating). Tag each piece of evidence with its source:
186
+
187
+ | Evidence source tag | Meaning |
188
+ |---|---|
189
+ | `mcp` | Resolved via Serena MCP query |
190
+ | `source` | Source-level pattern match |
191
+ | `ir` | LLVM IR analysis |
192
+ | `asm` | Assembly analysis |
193
+ | `cfg` | Control-flow graph analysis |
194
+
195
+ MCP evidence alone (1 signal) produces `likely`. MCP + one additional signal (source, IR, CFG, or ASM) produces `confirmed`.
196
+
197
+ **Mandatory downgrades** — applied by `apply_confidence_gates.py` after all evidence is collected:
198
+
199
+ | Condition | Findings downgraded to `needs_review` |
200
+ |---|---|
201
+ | `mcp_available=false` AND `mcp_required_for_advanced=true` | `SECRET_COPY`, `MISSING_ON_ERROR_PATH`, `NOT_DOMINATING_EXITS` (unless 2+ non-MCP signals exist) |
202
+ | Assembly evidence missing | `STACK_RETENTION`, `REGISTER_SPILL` |
203
+ | IR diff evidence missing | `OPTIMIZED_AWAY_ZEROIZE` |
204
+
205
+ Apply downgrades after all evidence is collected, not during querying. Do not suppress findings preemptively — emit at `needs_review` rather than dropping them.
206
+
207
+ ---
208
+
209
+ ## Post-Processing
210
+
211
+ After collecting all MCP evidence and running IR/ASM/CFG analysis, apply confidence gates mechanically:
212
+
213
+ ```bash
214
+ python {baseDir}/tools/mcp/apply_confidence_gates.py \
215
+ --input /tmp/raw-report.json \
216
+ --out /tmp/final-report.json \
217
+ --mcp-available \
218
+ --mcp-required-for-advanced
219
+ ```
220
+
221
+ Omit `--mcp-available` if MCP was unreachable. Omit `--mcp-required-for-advanced` if `mcp_required_for_advanced=false` in the run config. The script applies all downgrade rules from SKILL.md and outputs gated findings ready for the report assembly phase.
@@ -0,0 +1,470 @@
1
+ # PoC Crafting Reference
2
+
3
+ ## Overview
4
+
5
+ Each zeroize-audit finding is demonstrated with a bespoke proof-of-concept program
6
+ crafted from the finding details and the actual source code. PoCs are individually
7
+ written, not generated from templates — they use the real function signatures,
8
+ variable names, types, and sizes from the audited codebase. Each PoC exits 0 if the
9
+ secret persists (exploitable) or 1 if the data was properly wiped (not exploitable).
10
+
11
+ ## Exit Code Convention
12
+
13
+ | Exit code | Meaning |
14
+ |-----------|---------|
15
+ | 0 | Secret persists after the operation — finding is exploitable |
16
+ | 1 | Secret was wiped — finding is not exploitable in this configuration |
17
+
18
+ The `POC_PASS()` and `POC_FAIL()` macros in `poc_common.h` enforce this convention.
19
+
20
+ ## Common Techniques
21
+
22
+ ### Volatile Reads
23
+
24
+ The core verification technique is reading through a `volatile` pointer after the
25
+ function under test returns. This prevents the compiler from optimizing away the
26
+ read, ensuring we observe the actual memory state:
27
+
28
+ ```c
29
+ static int volatile_read_nonzero(const void *ptr, size_t len) {
30
+ const volatile unsigned char *p = (const volatile unsigned char *)ptr;
31
+ int found = 0;
32
+ for (size_t i = 0; i < len; i++) {
33
+ if (p[i] != 0) found = 1;
34
+ }
35
+ return found;
36
+ }
37
+ ```
38
+
39
+ ### Stack Probing
40
+
41
+ For `STACK_RETENTION` and `REGISTER_SPILL` findings, the PoC calls the target
42
+ function then immediately calls `stack_probe()` — a `noinline`/`noclone` function
43
+ that reads uninitialized local variables to detect whether the prior call frame left
44
+ secret data on the stack:
45
+
46
+ ```c
47
+ __attribute__((noinline, noclone))
48
+ static int stack_probe(size_t frame_size) {
49
+ volatile unsigned char probe[STACK_PROBE_MAX];
50
+ /* Read uninitialized stack — check for secret fill pattern */
51
+ int count = 0;
52
+ for (size_t i = 0; i < frame_size; i++) {
53
+ if (probe[i] == SECRET_FILL_BYTE) count++;
54
+ }
55
+ return count >= (int)(frame_size / 4);
56
+ }
57
+ ```
58
+
59
+ ### Source Inclusion
60
+
61
+ For static functions and small files (<=5000 lines by default), PoCs include the
62
+ source file directly via `#include "../../src/crypto.c"`. This handles both static
63
+ and extern functions without requiring separate compilation. For large files with
64
+ non-static functions, the Makefile uses object-file linking instead.
65
+
66
+ ### Secret Fill Pattern
67
+
68
+ Buffers are initialized with `0xAA` (configurable via `secret_fill_byte` in config)
69
+ before calling the target function. After the call, the PoC checks whether the fill
70
+ pattern persists — indicating the secret was not wiped.
71
+
72
+ ## Per-Category Strategies
73
+
74
+ ### MISSING_SOURCE_ZEROIZE
75
+
76
+ **Opt level:** `-O0`
77
+ **Technique:** Call the function that handles the secret, then volatile-read the
78
+ buffer after it returns. At `-O0` there are no optimization passes that could
79
+ accidentally wipe the buffer, so if the secret persists, it confirms the source
80
+ code lacks a wipe call.
81
+
82
+ **Crafting guidance:**
83
+ - Read the function signature and determine minimal valid arguments
84
+ - Identify the exact sensitive variable from the finding — use its real name and type
85
+ - If the function takes the sensitive buffer as a parameter, allocate it in `main()`,
86
+ fill with `SECRET_FILL_BYTE`, pass it to the function, then check after return
87
+ - If the sensitive variable is a local, include the source file and examine the buffer
88
+ via a global pointer or by modifying the function to expose it
89
+
90
+ **Pitfalls:**
91
+ - The buffer must be the actual sensitive variable, not a local copy
92
+ - Stack-allocated secrets may be overwritten by subsequent function calls even
93
+ without explicit zeroization — run immediately after the function returns
94
+
95
+ ### OPTIMIZED_AWAY_ZEROIZE
96
+
97
+ **Opt level:** The level where the wipe disappears (from `compiler_evidence.diff_summary`)
98
+ **Technique:** Same as `MISSING_SOURCE_ZEROIZE`, but compiled at the optimization
99
+ level where the compiler removes the wipe. The finding's `compiler_evidence` field
100
+ indicates which level this is (typically `-O1` for simple DSE, `-O2` for aggressive
101
+ optimization).
102
+
103
+ **Crafting guidance:**
104
+ - Read the `compiler_evidence.diff_summary` to determine the exact optimization level
105
+ - The wipe IS present at `-O0` — compiling the PoC at `-O0` will show "not exploitable"
106
+ which would be misleading. Always use the opt level from the evidence.
107
+ - Include the source file to ensure the compiler can apply the same optimizations
108
+
109
+ **Pitfalls:**
110
+ - The opt level must match what `diff_ir.sh` reported — compiling at a different
111
+ level may give false negatives
112
+ - LTO can change behavior; PoCs use single-TU compilation by default
113
+
114
+ ### STACK_RETENTION
115
+
116
+ **Opt level:** `-O2`
117
+ **Technique:** Call the function, then immediately call `stack_probe()` with a
118
+ frame size matching the target function's stack allocation. The probe reads
119
+ uninitialized locals that overlap the prior call frame.
120
+
121
+ **Crafting guidance:**
122
+ - Extract the stack frame size from the ASM evidence in the finding
123
+ - The probe function MUST be called immediately after the target function returns,
124
+ with no intervening function calls that could overwrite the stack
125
+ - Use `noinline` and `noclone` on the probe to prevent frame reuse
126
+
127
+ **Pitfalls:**
128
+ - Stack layout varies between compiler versions and optimization levels
129
+ - The probe function must be `noinline` to prevent the compiler from reusing
130
+ the same frame
131
+ - Frame size is estimated from ASM evidence; verify against the actual assembly
132
+ - Address Space Layout Randomization (ASLR) does not affect stack frame reuse
133
+ within a single thread
134
+
135
+ ### REGISTER_SPILL
136
+
137
+ **Opt level:** `-O2`
138
+ **Technique:** Similar to stack retention, but targets the specific stack offset
139
+ where the register spill occurs (extracted from the ASM evidence showing
140
+ `movq %reg, -N(%rsp)`).
141
+
142
+ **Crafting guidance:**
143
+ - Extract the exact spill offset from the finding's ASM evidence
144
+ - Target the probe at that specific region of the stack
145
+ - The same `noinline` probe approach applies
146
+
147
+ **Pitfalls:**
148
+ - Spill offsets are compiler-specific and may change with minor code changes
149
+ - Different register allocation strategies produce different spill patterns
150
+ - The probe must target the exact offset region to be reliable
151
+
152
+ ### SECRET_COPY
153
+
154
+ **Opt level:** `-O0`
155
+ **Technique:** Call the function that copies the secret, verify the original may
156
+ be wiped, then volatile-read the copy destination to confirm the copy persists
157
+ without zeroization.
158
+
159
+ **Crafting guidance:**
160
+ - Identify the copy destination from the source code: `memcpy` target, struct
161
+ assignment LHS, return value receiver, or pass-by-value parameter
162
+ - The PoC must check the COPY, not the original — the original may be wiped
163
+ - If the copy is to a struct field, allocate the struct and check that specific field
164
+
165
+ **Pitfalls:**
166
+ - The copy destination must be identified from the source code
167
+ - Multiple copies may exist; each needs separate verification
168
+
169
+ ### MISSING_ON_ERROR_PATH
170
+
171
+ **Opt level:** `-O0`
172
+ **Technique:** Force the error path by providing controlled inputs that trigger
173
+ the error return, then volatile-read the secret buffer to confirm it was not
174
+ wiped before the error exit.
175
+
176
+ **Crafting guidance:**
177
+ - Read the source code to understand what conditions trigger the error return
178
+ - Common error triggers: NULL pointer arguments, invalid key sizes, allocation
179
+ failure (can use `malloc` interposition), invalid magic numbers
180
+ - After the function returns with an error code, check both the return value
181
+ (to confirm the error path was taken) AND the secret buffer (to confirm it persists)
182
+ - Comment the choice of error-triggering input with a reference to the source line
183
+
184
+ **Pitfalls:**
185
+ - Triggering the error path may require domain knowledge (invalid keys, NULL
186
+ pointers, allocation failures)
187
+ - Some error paths involve signals or `longjmp` that are hard to trigger from
188
+ a simple test harness
189
+ - Error codes must be checked to confirm the error path was actually taken
190
+
191
+ ### PARTIAL_WIPE
192
+
193
+ **Opt level:** `-O0`
194
+ **Technique:** Fill the full buffer with the secret fill pattern, call the function,
195
+ then volatile-read the *tail* beyond the incorrectly-sized wipe region. If the
196
+ function wipes only N bytes of an M-byte object (N < M), the tail
197
+ `buf[N..M]` still contains the secret.
198
+
199
+ **Crafting guidance:**
200
+ - Extract the wiped size and full object size from the finding evidence
201
+ - The PoC must check `buf[wiped_size .. full_size]`, not the entire buffer
202
+ - If both sizes are uncertain, read the source to verify `sizeof()` calls
203
+
204
+ **Pitfalls:**
205
+ - The wiped vs. full sizes must be verified against source
206
+ - At `-O0` the compiler won't add extra zeroing, so this is a pure source-level bug
207
+ - Struct padding may cause false positives if the wipe intentionally skips padding
208
+
209
+ ### NOT_ON_ALL_PATHS
210
+
211
+ **Opt level:** `-O0`
212
+ **Technique:** Force execution down the control-flow path that lacks the wipe,
213
+ then volatile-read the secret buffer. This is structurally identical to
214
+ `MISSING_ON_ERROR_PATH` but covers *any* uncovered path, not just error paths.
215
+
216
+ **Crafting guidance:**
217
+ - Read the function's control flow to identify which branch lacks the wipe
218
+ - Determine what input values force execution through that branch
219
+ - Comment the input choice and reference the specific branch condition
220
+
221
+ **Pitfalls:**
222
+ - Requires understanding the function's branching logic
223
+ - The heuristic finding from source analysis may be superseded by CFG-backed
224
+ `NOT_DOMINATING_EXITS` — check for duplicates
225
+ - Multiple uncovered paths may exist; the PoC demonstrates only one
226
+
227
+ ### INSECURE_HEAP_ALLOC
228
+
229
+ **Opt level:** `-O0`
230
+ **Technique:** Demonstrate heap residue using the `heap_residue_check()` helper:
231
+ allocate with `malloc()`, fill with secret, free, re-allocate the same size,
232
+ then check if the secret persists in the new allocation. This proves that
233
+ standard allocators do not scrub freed memory.
234
+
235
+ **Crafting guidance:**
236
+ - Use the exact allocation size from the finding
237
+ - For a function-specific proof, call the target function (which does the
238
+ malloc/use/free), then immediately malloc the same size and check
239
+ - Add a comment explaining that this demonstrates the general vulnerability
240
+
241
+ **Pitfalls:**
242
+ - Do **not** compile with AddressSanitizer (`-fsanitize=address`) — ASan poisons
243
+ freed memory, hiding the vulnerability
244
+ - Heap allocator behavior varies: glibc `malloc` reuses freed chunks predictably,
245
+ but jemalloc or tcmalloc may not — the PoC may give false negatives on
246
+ non-standard allocators
247
+ - The PoC demonstrates the general vulnerability; for function-level proof,
248
+ call the actual target function
249
+
250
+ ### LOOP_UNROLLED_INCOMPLETE
251
+
252
+ **Opt level:** `-O2`
253
+ **Technique:** Like `PARTIAL_WIPE` but compiled at `-O2` where incomplete loop
254
+ unrolling occurs. The compiler unrolls the wipe loop for N bytes but the object
255
+ is M bytes (N < M). Fill the buffer, call the function, check the tail beyond
256
+ the unrolled region.
257
+
258
+ **Crafting guidance:**
259
+ - Extract the covered bytes and object size from the IR semantic analysis evidence
260
+ - Compile at `-O2` — at `-O0` the loop executes correctly
261
+ - Check `buf[covered_bytes .. object_size]`
262
+
263
+ **Pitfalls:**
264
+ - Must compile at `-O2` (or the level where unrolling occurs) — at `-O0` the
265
+ loop executes correctly
266
+ - Covered bytes and object size are extracted from IR semantic analysis evidence;
267
+ if the IR evidence is unavailable, values may be inaccurate
268
+ - Different compilers (GCC vs. Clang) and versions unroll differently; the PoC
269
+ is compiler-specific
270
+
271
+ ### NOT_DOMINATING_EXITS
272
+
273
+ **Opt level:** `-O0`
274
+ **Technique:** Force execution through an exit path that bypasses the wipe, as
275
+ identified by CFG dominator analysis. The wipe node does not dominate all exit
276
+ nodes, meaning some return paths leave the secret in memory.
277
+
278
+ **Crafting guidance:**
279
+ - Read the finding evidence to identify which exit path bypasses the wipe
280
+ - Determine what inputs reach the non-dominated exit
281
+ - Comment the input choice and reference the CFG evidence (exit line or path count)
282
+
283
+ **Pitfalls:**
284
+ - Requires understanding of the function's CFG; the finding evidence identifies
285
+ the exit line or path count
286
+ - Similar to `NOT_ON_ALL_PATHS` but backed by CFG evidence rather than
287
+ source-level heuristics
288
+
289
+ ## Pipeline Integration
290
+
291
+ PoC crafting and validation is mandatory for every finding, regardless of
292
+ confidence level. The pipeline flow is:
293
+
294
+ 1. **Phase 3 — Interim Finding Collection**: Agent 4 produces `findings.json`
295
+ with all gated findings. No final report yet.
296
+
297
+ 2. **Phase 4 — PoC Crafting**: Agent 5 reads each finding and the corresponding
298
+ source code, then writes bespoke PoC programs. Each PoC is individually
299
+ tailored — using real function names, variable names, types, and sizes.
300
+
301
+ 3. **Phase 5 — PoC Validation & Verification**:
302
+ - Agent 5b compiles and runs all PoCs, recording exit codes.
303
+ - Agent 5c verifies each PoC proves its claimed finding by checking:
304
+ target variable match, target function match, technique appropriateness,
305
+ optimization level, exit code interpretation, and result plausibility.
306
+ - Orchestrator presents verification failures to user via `AskUserQuestion`.
307
+ - Orchestrator merges all results into `poc_final_results.json`.
308
+
309
+ 4. **Phase 6 — Report Finalization**: Agent 4 is re-invoked in final mode.
310
+ It merges PoC validation and verification results into findings:
311
+ - Exit 0 + verified → `exploitable` — strong evidence, can upgrade confidence.
312
+ - Exit 1 + verified → `not_exploitable` — downgrade severity to `low`.
313
+ - Verified=false + user rejected → `rejected` — no confidence change.
314
+ - Verified=false + user accepted → use result but note as weaker signal.
315
+ - Compile failure → annotate, no confidence change.
316
+ - Produces the final `final-report.md` with PoC validation and verification summary.
317
+
318
+ ### Validation Result Mapping
319
+
320
+ | Exit Code | Compile | Verified | Result | Finding Impact |
321
+ |-----------|---------|----------|--------|---------------|
322
+ | 0 | success | yes | `exploitable` | Confirm finding; can upgrade `likely` → `confirmed` |
323
+ | 1 | success | yes | `not_exploitable` | Downgrade severity to `low` (informational) |
324
+ | 0/1 | success | no (user accepted) | original | Weaker confidence signal; note verification failure |
325
+ | 0/1 | success | no (user rejected) | `rejected` | No confidence change |
326
+ | — | failure | — | `compile_failure` | Annotate; no confidence change |
327
+ | — | — | — | `no_poc` | No PoC generated; annotate; no confidence change |
328
+
329
+ ## Rust PoC Generation
330
+
331
+ Rust PoCs are enabled for three categories where a simple volatile-read after drop is sufficient to prove the vulnerability. All other categories remain excluded.
332
+
333
+ **Exit code convention (cargo test):**
334
+ - `assert!` passes → cargo exits 0 → `"exploitable"` (secret persists)
335
+ - `assert!` panics → cargo exits non-zero → `"not_exploitable"` (secret wiped)
336
+
337
+ **Verification primitive:** Use `std::ptr::read_volatile` inside `unsafe { }`. Never use the C `volatile` keyword in Rust PoCs.
338
+
339
+ **Pointer validity:** `read_volatile` after `drop()` is only safe for heap-backed data. If the sensitive type is stack-only, force heap allocation: `let boxed = Box::new(obj); let raw = boxed.as_ref().as_ptr(); drop(boxed);`. For types with `Vec`/`Box` fields, the raw pointer to the field's backing allocation remains valid after drop (the heap page is not scrubbed by the allocator).
340
+
341
+ ---
342
+
343
+ ### MISSING_SOURCE_ZEROIZE (Rust)
344
+
345
+ **Opt level:** debug (no `--release`)
346
+ **Technique:** Construct the sensitive type with `[0xAAu8; N]` fill. Capture a raw pointer to the backing buffer **before** drop. Drop the type (or let scope end). Volatile-read the buffer to check persistence.
347
+
348
+ ```rust
349
+ #[test]
350
+ fn poc_za_NNNN_missing_source_zeroize() {
351
+ let key = SensitiveKey::new([0xAAu8; 32]);
352
+ let raw: *const u8 = key.as_slice().as_ptr();
353
+ drop(key);
354
+ let secret_persists = (0..32usize).any(|i| unsafe {
355
+ std::ptr::read_volatile(raw.add(i)) == 0xAA
356
+ });
357
+ assert!(secret_persists, "Secret was wiped — not exploitable");
358
+ }
359
+ ```
360
+
361
+ **Pitfalls:**
362
+ - The raw pointer must point to heap-backed storage — stack pointers become dangling after drop.
363
+ - If the type does not expose `as_slice()` or similar, use a field accessor (`key.key_bytes.as_ptr()`).
364
+ - At debug build, the compiler does not add extra zeroing — a positive result confirms the source lacks a wipe call.
365
+
366
+ ---
367
+
368
+ ### SECRET_COPY (Rust)
369
+
370
+ **Opt level:** debug (no `--release`)
371
+ **Technique:** Perform the identified copy operation (`.clone()`, `Copy` assignment, `From::from()`, `Debug` formatting). Drop the **original**. Volatile-read the **copy** — not the original.
372
+
373
+ ```rust
374
+ #[test]
375
+ fn poc_za_NNNN_secret_copy() {
376
+ let original = SensitiveKey::new([0xAAu8; 32]);
377
+ let copy = original.clone(); // or Copy assignment / From::from()
378
+ let raw: *const u8 = copy.as_slice().as_ptr();
379
+ drop(original); // original may be wiped; copy is not
380
+ let secret_persists = (0..32usize).any(|i| unsafe {
381
+ std::ptr::read_volatile(raw.add(i)) == 0xAA
382
+ });
383
+ drop(copy);
384
+ assert!(secret_persists, "Copy was wiped — not exploitable");
385
+ }
386
+ ```
387
+
388
+ **Pitfalls:**
389
+ - Read the copy, not the original. The original may be properly wiped; the copy is the vulnerability.
390
+ - For `#[derive(Debug)]` findings: format via `format!("{:?}", &original)` and check the resulting `String` for the fill pattern bytes (hex or decimal representations of `0xAA`).
391
+ - For `From`/`Into` findings: call the conversion and check the target type's buffer.
392
+
393
+ ---
394
+
395
+ ### PARTIAL_WIPE (Rust)
396
+
397
+ **Opt level:** debug (no `--release`)
398
+ **Technique:** Construct the type with `[0xAAu8; full_size]` fill. Trigger drop. Volatile-read **only the tail** (`wiped_size..full_size`). The head (`0..wiped_size`) may be correctly zeroed; only the tail proves the partial wipe.
399
+
400
+ ```rust
401
+ #[test]
402
+ fn poc_za_NNNN_partial_wipe() {
403
+ // full_size = 64, wiped_size = 32 (from finding evidence)
404
+ let obj = SensitiveStruct { key: [0xAAu8; 64], ..Default::default() };
405
+ let raw: *const u8 = obj.key.as_ptr();
406
+ drop(obj);
407
+ // Only check the tail bytes beyond the wipe region
408
+ let tail_persists = (32usize..64).any(|i| unsafe {
409
+ std::ptr::read_volatile(raw.add(i)) == 0xAA
410
+ });
411
+ assert!(tail_persists, "Tail was wiped — not exploitable");
412
+ }
413
+ ```
414
+
415
+ **Pitfalls:**
416
+ - Must check `buf[wiped_size..full_size]`, not the entire buffer — checking from 0 may hit correctly-wiped bytes and produce a false negative.
417
+ - Extract `wiped_size` and `full_size` from the finding evidence. Verify against `sizeof()` calls in the Drop impl.
418
+ - Struct padding may occupy bytes beyond the last field — be aware of layout differences with `#[repr(C)]` vs. default `#[repr(Rust)]`.
419
+
420
+ ---
421
+
422
+ ## Excluded Rust Categories
423
+
424
+ The following Rust finding categories remain `poc_supported=false`. Each requires techniques not yet implemented for Rust.
425
+
426
+ | Category | Reason |
427
+ |---|---|
428
+ | `OPTIMIZED_AWAY_ZEROIZE` | Requires compiling at `--release` and confirming the wipe existed at debug level; no PoC harness for opt-level switching |
429
+ | `STACK_RETENTION` | Stack probe requires unsafe inline assembly intrinsics; frame layout is not stable across Rust versions |
430
+ | `REGISTER_SPILL` | Register allocation in Rust depends on monomorphization; spill offsets from ASM analysis don't map reliably to test code |
431
+ | `NOT_ON_ALL_PATHS` | Requires driving async Future state machine through suspension; no implemented harness for Rust async |
432
+ | `MISSING_ON_ERROR_PATH` | Requires forcing `Result::Err` or `panic!` paths with domain knowledge of the error conditions |
433
+ | `NOT_DOMINATING_EXITS` | CFG dominator analysis results require source-level forcing of specific control-flow paths |
434
+ | `INSECURE_HEAP_ALLOC` | Rust's allocator trait system does not support the `malloc`-interposition approach used for C |
435
+ | `LOOP_UNROLLED_INCOMPLETE` | Requires `--release` compilation and extracting the covered-byte count from IR evidence |
436
+
437
+ ## Limitations
438
+
439
+ 1. **Stack probe is probabilistic:** Frame layout varies between compiler versions,
440
+ optimization levels, and even minor source changes. A negative result does not
441
+ prove the stack is clean — only that the probe did not find the fill pattern at
442
+ the expected offset.
443
+
444
+ 2. **Register spill offsets are compiler-specific:** The offset extracted from
445
+ ASM evidence (e.g., `-48(%rsp)`) may differ when compiled on a different system
446
+ or with a different compiler version.
447
+
448
+ 3. **Error path triggers may need domain knowledge:** Determining what inputs cause
449
+ a function to take its error path may require understanding the application's
450
+ protocol or data format.
451
+
452
+ 4. **Source inclusion may cause conflicts:** Including a `.c` file that defines
453
+ `main()` or has conflicting global symbols will cause compilation errors. In
454
+ these cases, use object-file linking instead.
455
+
456
+ 5. **Single-TU compilation:** PoCs compile a single translation unit. Cross-TU
457
+ optimizations (LTO) may produce different behavior in production builds.
458
+
459
+ 6. **No dynamic analysis:** PoCs are static programs. They do not use sanitizers,
460
+ Valgrind, or other runtime instrumentation (those are covered by Step 11's
461
+ runtime test generation).
462
+
463
+ 7. **Heap residue is allocator-dependent:** The `heap_residue_check()` helper
464
+ relies on the allocator reusing a recently-freed chunk. This works reliably
465
+ with glibc `malloc` but may produce false negatives with jemalloc, tcmalloc,
466
+ or custom allocators. Do not compile with ASan (it poisons freed memory).
467
+
468
+ 8. **Verification is heuristic:** The PoC verifier checks alignment between the
469
+ PoC and the finding, but cannot prove that a PoC is correct in all cases.
470
+ Suspicious results are flagged for user review.