> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fallow.tools/llms.txt
> Use this file to discover all available pages before exploring further.

# Security agent verification

> Turn fallow security candidates into verifier-filtered survivor reports without adding model calls to fallow.

`fallow security` produces deterministic candidates. It does not call a model, decide exploitability, or emit verified vulnerabilities. Use this recipe when an agent or external harness should turn raw candidates into a shorter survivor list.

## Inputs

Use the CLI when you want a standalone JSON file:

```bash theme={null}
fallow security --format json --surface --quiet > fallow-security.json
```

Use MCP when an agent is already in an edit loop:

```json theme={null}
{
  "root": "/path/to/repo",
  "surface": true,
  "paths": ["src/routes/login.ts"]
}
```

`surface: true` forwards `--surface` and includes top-level `attack_surface[]` entries. Set `gate` to `new` for changed-line candidates or `newly-reachable` for candidates that became reachable from entry points; `newly-reachable` requires `changed_since`. `paths` forwards repeated `--file` filters and scopes returned candidates to matching anchors, trace hops, source-trace hops, and unresolved-callee diagnostics.

Each candidate includes `severity`, a review-priority tier (`high`, `medium`, or `low`). It is not a verified vulnerability verdict. When `reachability.taint_confidence` is present, use it to distinguish `arg-level` source association from weaker `module-level` reachability.

## Verifier packet

For each `security_findings[]` item, build one packet from deterministic fallow evidence plus caller-collected source windows:

```json theme={null}
{
  "schema_version": "fallow-security-verifier-input/v1",
  "finding_id": "security:...",
  "severity": "high",
  "candidate": {
    "source_kind": "http-request-input",
    "sink": {},
    "boundary": {}
  },
  "trace": [],
  "taint_flow": null,
  "taint_confidence": "arg-level",
  "reachability_trace": [],
  "attack_surface": null,
  "source_windows": [
    {
      "path": "src/routes/login.ts",
      "start_line": 12,
      "end_line": 52,
      "text": "..."
    }
  ],
  "blind_spots": {
    "unresolved_edge_files": 0,
    "unresolved_callee_sites": 0,
    "unresolved_callee_diagnostics": null
  }
}
```

Collect source windows from disk after the scan. Keep them outside fallow output so the core stays deterministic, compact, and provider-neutral.

`blind_spots.unresolved_callee_diagnostics` can copy the top-level fallow output when a verifier queue wants sample locations for dynamic-dispatch follow-up. It is bounded metadata, not proof of a vulnerability.

## Prompt contract

Ask the verifier to dismiss candidates unless the supplied evidence supports a real exploit path:

```text theme={null}
You are verifying one fallow security candidate.

Fallow is a deterministic candidate producer, not a vulnerability oracle.
Use only the supplied candidate, trace, attack-surface entry, and source windows.
Do not assume data flow beyond the provided code.

Check:
1. Is the input attacker-controlled?
2. Does the value reach the reported sink?
3. Is the reported boundary relevant to exploitability?
4. What concrete impact would remain if the candidate is real?
5. Is there an existing defensive control that dismisses it?

Return only JSON matching fallow-security-verdict/v1.
```

If `attack_surface.defensive_boundary.verification_prompt` is present, include it as an additional question, not as a verdict.

## Verdict schema

Require a compact JSON verdict:

```json theme={null}
{
  "schema_version": "fallow-security-verdict/v1",
  "finding_id": "security:...",
  "verdict": "survivor",
  "reason": "The request query value reaches execSync without validation.",
  "impact": "Command injection through the id query parameter.",
  "evidence_checked": {
    "source": true,
    "sink": true,
    "boundary": true,
    "trace": true,
    "source_window": true
  },
  "dismissal_reason": null,
  "fix_direction": "avoid-shell"
}
```

Allowed verdicts:

* `survivor`: the verifier could not dismiss the candidate from the supplied evidence.
* `dismissed`: the candidate is not exploitable from the supplied evidence.
* `needs-human-review`: the evidence is incomplete, contradictory, or blocked by missing context.

Store verifier output beside the original fallow JSON, keyed by `finding_id`. Do not write verdict fields back into fallow output.

## Render survivors

Join the candidates and the verdict file with [`fallow security survivors`](/cli/security#survivors) to render only the candidates the verifier retained:

```bash theme={null}
fallow security --format json --quiet > candidates.json
# (verifier writes verdicts.json keyed by finding_id)
fallow security survivors --candidates candidates.json --verdicts verdicts.json
```

It reports `summary.unverdicted` so unreviewed candidates stay visible; add `--require-verdict-for-each-candidate` to fail CI when any candidate lacks a verdict. To see where the structural trace stopped (unresolved callees the verifier should inspect by hand), run [`fallow security blind-spots`](/cli/security#blind-spots).

## Caveats

Candidate quality depends on source and trace fidelity. HTTP-input source patterns are receiver-gated to avoid broad `*.query` collisions with unrelated APIs, but framework-specific request aliases can still need verifier judgment. `reachability.taint_confidence` distinguishes `arg-level` from `module-level` source association; use `severity` and `taint_confidence` for triage order, then verify source control, value flow, sink behavior, and defensive controls from source windows before reporting a survivor.

## See also

<CardGroup cols={2}>
  <Card title="fallow security" icon="shield" href="/cli/security">
    CLI reference for security candidates.
  </Card>

  <Card title="MCP integration" icon="plug" href="/integrations/mcp">
    Agent setup and tool contracts.
  </Card>
</CardGroup>
