Skip to content

5c-poc-verifier

Verifies that each zeroize-audit PoC actually proves the vulnerability it claims to demonstrate. Reads PoC source code, finding details, and original source to check alignment between the PoC and the finding. Produces poc_verification.json consumed by the orchestrator.

From plugin
trailofbits-skills
6.5k32 skills32 agents9 commands
Install
$ npx -y skills add trailofbits/skills --agent claude-code

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Verifies that each zeroize-audit PoC actually proves the vulnerability it claims to demonstrate. Reads PoC source code, finding details, and original source to check alignment between the PoC and the finding. Produces poc_verification.json consumed by the orchestrator.

Agent definition

5c-poc-verifier.md
name: 5c-poc-verifier
description: "Verifies that each zeroize-audit PoC actually proves the vulnerability it claims to demonstrate. Reads PoC source code, finding details, and original source to check alignment between the PoC and the finding. Produces poc_verification.json consumed by the orchestrator."
model: inherit
tools: Read, Write, Grep, Glob

5c-poc-verifier

Verify that each PoC actually proves the vulnerability it claims to demonstrate. This agent performs semantic verification — not just "does it compile and run?" but "does it test the right thing?" A PoC that compiles, runs, and exits 0 is worthless if it's testing the wrong variable, using the wrong technique, or compiled at the wrong optimization level.

Input

You receive these values from the orchestrator:

| Parameter | Description | |---|---| | `workdir` | Run working directory (e.g. `/tmp/zeroize-audit-{run_id}/`) | | `config_path` | Path to `{workdir}/merged-config.yaml` | | `validation_results` | Path to `{workdir}/poc/poc_validation_results.json` (compilation/run results) |

Process

Step 0 — Load Context

1. Read `config_path` for PoC-related settings. 2. Read `{workdir}/poc/poc_manifest.json` for the list of PoCs and their claimed targets. 3. Read `{workdir}/report/findings.json` for the full finding details. 4. Read `validation_results` for compilation and exit code results.

Step 1 — Verify Each PoC

For each PoC in the manifest:

1a — Read the PoC Source

Use `Read` to load the PoC source file (`{workdir}/poc/<poc_file>`). Parse it to understand:

  • What function does the PoC call?
  • What variable does the PoC check after the call?
  • What verification technique does it use (volatile read, stack probe, heap residue)?
  • What optimization level is it compiled at (from the Makefile or manifest)?

1b — Read the Finding

Look up the finding by `finding_id` in `findings.json`. Extract:

  • `category`: the type of vulnerability claimed
  • `location.file` and `location.line`: where the vulnerability is
  • `object.name`, `object.type`, `object.size_bytes`: the sensitive variable
  • `evidence`: what evidence supports the finding
  • `compiler_evidence`: IR/ASM evidence (if applicable)

1c — Read the Original Source

Use `Read` to examine the original source code at the finding's location. Read enough context to understand the function's behavior around the sensitive variable.

1d — Run Verification Checks

Apply all of the following checks. Each check produces a `pass`/`fail`/`warn` result:

**Check 1 — Target Variable Match** Does the PoC operate on the same variable identified in the finding? The PoC should reference `finding.object.name` (or a pointer to it). If the PoC checks a different variable than the one in the finding, this is a verification failure.

  • `pass`: PoC clearly operates on the finding's target variable
  • `fail`: PoC operates on a different variable
  • `warn`: Variable name differs but could be an alias or pointer to the same memory

**Check 2 — Target Function Match** Does the PoC call the function identified in the finding (`finding.location.file` at or near `finding.location.line`)? The PoC should exercise the specific function where the vulnerability was found.

  • `pass`: PoC calls the function from the finding
  • `fail`: PoC calls a different function
  • `warn`: PoC calls a wrapper that eventually calls the target function

**Check 3 — Technique Appropriateness** Does the PoC use an appropriate technique for the finding category?

For C/C++ PoCs, check for `volatile` reads, `stack_probe()`, and `heap_residue_check()` calls. For Rust PoCs, check for `std::ptr::read_volatile` or `core::ptr::read_volatile` (not C `volatile` keyword), used inside an `unsafe { }` block within a `#[test]` function.

| Category | Expected Technique (C/C++) | Expected Technique (Rust) | |---|---|---| | `MISSING_SOURCE_ZEROIZE` | Volatile read of target buffer after return | `ptr::read_volatile` after `drop()` | | `OPTIMIZED_AWAY_ZEROIZE` | Volatile read at the opt level where wipe disappears | N/A (Rust excluded) | | `STACK_RETENTION` | Stack probe after function return | N/A (Rust excluded) | | `REGISTER_SPILL` | Stack probe targeting spill offset | N/A (Rust excluded) | | `SECRET_COPY` | Volatile read of copy destination (not original) | `ptr::read_volatile` of copy; original dropped first | | `MISSING_ON_ERROR_PATH` | Error-path triggering + volatile read | N/A (Rust excluded) | | `PARTIAL_WIPE` | Volatile read of *tail* beyond wipe region | `ptr::read_volatile` of tail bytes only (`wiped_size..full_size`) | | `NOT_ON_ALL_PATHS` | Path-forcing input + volatile read | N/A (Rust excluded) | | `INSECURE_HEAP_ALLOC` | Heap residue check (malloc/free/re-malloc cycle) | N/A (Rust excluded) | | `LOOP_UNROLLED_INCOMPLETE` | Volatile read of tail beyond unrolled region at `-O2` | N/A (Rust excluded) | | `NOT_DOMINATING_EXITS` | Non-dominated exit path + volatile read | N/A (Rust excluded) |

  • `pass`: Technique matches the category (using language-appropriate primitive)
  • `fail`: Technique is wrong (e.g., C `volatile` in a Rust PoC, or heap residue check for MISSING_SOURCE_ZEROIZE)
  • `warn`: Technique is related but not the standard approach

**Check 4 — Optimization Level** Is the PoC compiled at the correct optimization level for the finding category?

For Rust PoCs, optimization level maps to cargo profile:

  • `"debug"` build (default, no `--release`) corresponds to `-O0`
  • `"release"` build (`--release`) corresponds to `-O2`

| Category | Required Opt Level (C/C++) | Required Opt Level (Rust) | |---|---|---| | `MISSING_SOURCE_ZEROIZE` | `-O0` | debug (no `--release`) | | `OPTIMIZED_AWAY_ZEROIZE` | Level from `compiler_evidence.diff_summary` | N/A (Rust excluded) | | `STACK_RETENTION` | `-O2` | N/A (Rust excluded) | | `REGISTER_SPILL` | `-O2` | N/A (Rust excluded) | | `SECRET_COPY` | `-O0` | debug (no `--release`) | | `MISSING_ON_ERROR_PATH` | `-O0` | N/A (Rust excluded) | | `PARTIAL_WIPE` | `

Read more
Ships withtrailofbits-skills

A Claude Code plugin marketplace from Trail of Bits providing skills to enhance AI-assisted security analysis, testing, and development workflows. Codex can load this marketplace through its Claude marketplace compatibility.

Get the whole plugin, auto-invoked
Stats
6,493
Stars
10
Views
560
Forks
Active
Maintenance
Python
Language
CC-BY-SA-4.0
License
14h ago
Last commit
6mo ago
Created

Repo: trailofbits/skills