> For the complete documentation index, see [llms.txt](https://docs.codna.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.codna.ai/guides/security-autofix.md).

# Security Autofix

Security Autofix ingests a SAST/SCA scanner's SARIF, proves reachability honestly, remediates only the findings that are genuinely fixable, and opens a draft pull request only when every safety condition holds — never on a guess. Use it when a scanner has produced hundreds of findings and you need to know which ones are real, and to auto-remediate the provable ones with an evidence-backed PR.

The command is `codna secure`. It runs in two tiers:

| Tier       | What it does                                               | LLM tokens      | Writes anything?                        |
| ---------- | ---------------------------------------------------------- | --------------- | --------------------------------------- |
| **Tier-1** | Classify reachability + autofix-eligibility (read-only)    | Zero            | No                                      |
| **Tier-2** | Remediate eligible findings: fix, verify, re-prove closure | Yes (patch-gen) | Only a draft PR, and only past the gate |

Start with Tier-1 — it is the fast, free wedge and the only step most findings ever need:

```bash
codna secure . --from-sarif results.sarif
```

## The end-to-end loop

Security Autofix is a single closed loop. Each step feeds the next; a failure at any step stops the loop and is named in the report. The work spans three privilege domains — the read-only **engine** classifies and re-proves closure, the sandboxed **worker** runs untrusted repo code with no write token, and the **writer** holds a scoped token and opens the PR but runs no repo code.

```mermaid
flowchart TD
    sarif[/SARIF report/] --> g1[Ingest · validate provenance · G1]
    g1 --> classify[Classify reachability<br/>engine · read-only]
    classify --> elig{Policy-eligible?<br/>G3}
    elig -->|no| report[Report only]
    elig -->|yes| worker
    subgraph worker["Worker · sandbox · no write token"]
        direction TB
        repro[Reproduce baseline · G2] --> patch[Generate patch]
        patch --> integ[Patch integrity · G4] --> build[Build + tests · G5]
        build --> rescan[Scanner rerun · G6]
    end
    worker --> closure[Re-prove closure · G7<br/>engine]
    closure --> gate{Gate · AND of G1–G9}
    gate -->|any fail| blocked[Blocked · reason named]
    gate -->|all pass| writer[Writer · scoped token<br/>verify attestation G9 → open draft PR]
```

{% stepper %}
{% step %}

#### Ingest SARIF

Codna reads the scanner's SARIF (CodeQL / Semgrep / Snyk / Trivy), validates its provenance (G1), and pins the snapshot. Only SARIF `2.1.0` is accepted, and the run must record a full 40-hex commit and a driver name + version.

```bash
codna secure . --from-sarif results.sarif
```

{% endstep %}

{% step %}

#### Classify reachability

Every finding gets exactly one of four verdicts — `exploitable`, `production-reachable`, `unreachable`, or `unknown`. This is read-only and spends zero LLM tokens. "No path found" is reported as `unknown` under any incomplete envelope, never as `unreachable`.
{% endstep %}

{% step %}

#### Remediate eligible

Tier-2, opt-in. Only autofix-eligible findings are touched (eligibility is decided by policy gate G3). For each one, a patch is generated in an isolated ephemeral worktree pinned to the scan commit.

```bash
codna secure . --from-sarif results.sarif --engine local --fix \
  --verification codna-security.yaml
```

{% endstep %}

{% step %}

#### Verify build / tests

The patch is integrity-checked (G4) before it is ever applied — a rejected patch is never applied. Then it is applied and the manifest's build + test commands run; a regression blocks the finding (G5).
{% endstep %}

{% step %}

#### Re-prove closure

The original security obligation is independently re-proven `closed` (G7). Closure is a separate judgment from reachability: the sink can stay production-reachable and the obligation still be closed once a recognized barrier is added.
{% endstep %}

{% step %}

#### PR gate

A draft PR opens only on the logical-AND of nine conditions (`G1`…`G9`), through the privilege-separated writer with a narrowly-scoped token. A single failure blocks the PR and is named in the report.

```bash
codna secure . --from-sarif results.sarif \
  --verification codna-security.yaml --open-pr
```

{% endstep %}
{% endstepper %}

## Command reference

`codna secure [repo] --from-sarif <results.sarif> [options]`

| Flag                      | Default                               | Purpose                                                                                                                                                                                      |
| ------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `repo` (positional)       | `.`                                   | Local path or git URL of the repository under analysis                                                                                                                                       |
| `--from-sarif PATH`       | — (required)                          | Scanner SARIF output (CodeQL / Semgrep / Snyk / Trivy)                                                                                                                                       |
| `--ref REF`               | repo default                          | Branch, tag, or commit to snapshot                                                                                                                                                           |
| `--engine {local,remote}` | `local`                               | Reachability engine — `local` is the packaged bounded, self-hostable reference; `remote` is an explicit full-engine override                                                                 |
| `--verification PATH`     | —                                     | `codna-security.yaml` manifest; required for `--open-pr` and for remote `--fix`                                                                                                              |
| `--fix`                   | off                                   | Remediate eligible findings; opens no PR. The default `--engine local` applies the verified patch to your checkout (re-verified there); `--engine remote` without `--open-pr` is report-only |
| `--open-pr`               | off                                   | Open a fix PR per eligible finding (requires `--engine remote` and a resolved manifest)                                                                                                      |
| `--github-token TOK`      | `$CODNA_GITHUB_TOKEN`/`$GITHUB_TOKEN` | Write token for `--open-pr`                                                                                                                                                                  |
| `--base-branch NAME`      | `main`                                | PR base branch                                                                                                                                                                               |
| `--repo-slug owner/repo`  | derived from git remote               | Target repo for `--open-pr`                                                                                                                                                                  |

Relevant environment variables:

| Variable                                                  | Used for                                                                                   |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `CODNA_API_KEY`                                           | Codna license / metering key                                                               |
| `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` | Provider key for model-backed remediation                                                  |
| `CODNA_GITHUB_TOKEN` / `GITHUB_TOKEN`                     | Write token. `secure --open-pr` accepts either; `secure-open-pr` reads `GITHUB_TOKEN` only |
| `CODNA_ATTESTATION_KEY`                                   | HMAC key shared between worker and writer (required for the two-job handoff)               |
| `CODNA_FIX_MODEL`                                         | Patch-generation model for `--engine local --fix`                                          |
| `CODNA_MODEL_PACK_DIGEST`                                 | Model-pack digest pinned into security provenance                                          |

## Tier-1: honest reachability proof

Codna ingests the scanner's SARIF, validates its provenance, and assigns every finding exactly one of four verdicts. This classification is read-only and spends zero LLM tokens — no patch generation, no build, no scanner rerun.

| Verdict                | Meaning                                                                            | Autofix-eligible?                     |
| ---------------------- | ---------------------------------------------------------------------------------- | ------------------------------------- |
| `exploitable`          | An independent source-to-sink taint path is proven                                 | Yes (policy default)                  |
| `production-reachable` | The vulnerable operation is callable in production; taint not independently proven | Only with an explicit policy override |
| `unreachable`          | No path, plus a complete, sound analysis envelope                                  | Never                                 |
| `unknown`              | No path under an incomplete or unsupported envelope                                | Never                                 |

```bash
codna secure . --from-sarif results.sarif --engine remote
```

```
codna: understanding . for security analysis …

✓ analyzed 4 finding(s) from results.sarif
  → [exploitable] sql-injection (taint)  autofix-eligible
  · [production-reachable] path-traversal (taint)  production-reachable requires an explicit policy override
  · [unreachable] xss-reflected (taint)  unreachable findings are never auto-fixed
  · [unknown] insecure-deserialization (taint)  unknown findings are never auto-fixed
  summary: exploitable=1, production-reachable=1, unknown=1, unreachable=1  ·  autofix-eligible: 1
```

{% hint style="info" %}
This output is from `--engine remote`. The default `--engine local` prints no banner and never claims `exploitable` — its strongest verdict is `production-reachable` — so a local run shows `[production-reachable]` in place of the `[exploitable]` row.
{% endhint %}

The leading `→` marks autofix-eligible findings; `·` marks the rest. The bracketed value is the reachability verdict; the parenthesized value is the finding kind (`taint`, `sca`, `control_flow`, `config`, `secret`, or `unsupported`).

{% hint style="danger" %}
**The cardinal honesty rule.** "No path found" is never silently reported as `unreachable`. A finding is `unreachable` only when the analysis envelope for that `(language, framework, build_mode)` is complete and sound. Under any incomplete or unsupported envelope, the absence of a path is reported as `unknown` — Codna does not know, and says so.
{% endhint %}

### Why an envelope can be incomplete

Reachability is only as trustworthy as the analysis that produced it. Codna keys completeness on `(language, framework, build_mode)` and falls back from most to least specific. Reflection-heavy stacks deliberately get a bounded envelope, because reflection makes "absence of a path" unprovable:

| Stack                                              | Envelope    | Strongest verdict it can assert              |
| -------------------------------------------------- | ----------- | -------------------------------------------- |
| `python`, `javascript`, `typescript`, `go`, `java` | complete    | `unreachable` / `production-reachable`       |
| `java + spring`                                    | bounded     | `production-reachable` (never `unreachable`) |
| `ruby`, `php`                                      | bounded     | `production-reachable`                       |
| any other language                                 | unsupported | `unknown` only                               |

A finding under a bounded envelope with no proven path is reported `unknown` (`bounded envelope: production-reachability not independently provable`), never `unreachable`. An off-matrix language yields `unknown` with proof type `off-matrix (<language>)`.

{% hint style="warning" %}
**The local classifier never claims `exploitable`.** The bounded local reference engine does not perform independent interprocedural taint analysis. Its strongest verdict is `production-reachable`. Only the full Codna reachability proof path can assert `exploitable`. Scanner code-flows are recorded as corroboration (`scanner-flow-corroborated`), never trusted as proof.
{% endhint %}

### Choosing the reachability engine

The same command runs against either engine. Pick the one that matches your trust and connectivity constraints:

{% tabs %}
{% tab title="Remote" icon="cloud" %}
The full Codna reachability proof path. It performs independent interprocedural taint analysis, so it is the **only** path that can earn the `exploitable` verdict. It is also the path that can drive `--open-pr` through the privilege-separated writer.

```bash
# Full Codna reachability proof path — can earn the 'exploitable' verdict (default)
codna secure . --from-sarif results.sarif --engine remote
```

Configure with your Codna account key. No separate analysis service is configured by the user.
{% endtab %}

{% tab title="Local" icon="server" %}
The bounded local reference engine — air-gapped, no external engine and no SAST scanner image. Its strongest verdict is `production-reachable`; it never claims `exploitable`. It can run a local fix loop that applies the verified patch to your checkout and re-runs verification there, but opens no PR — passing `--open-pr` with `--engine local` is refused.

```bash
# Bounded local classifier — ceiling of 'production-reachable'
codna secure . --from-sarif results.sarif --engine local
```

For the local fix loop, the patch comes from the Codna agent with the model named in `CODNA_FIX_MODEL`.
{% endtab %}
{% endtabs %}

Test-only sinks (paths matching `tests/`, `spec/`, `__tests__/`, or `*_test.*` / `*.test.*` / `*_spec.*`) are reported `unreachable` under a complete envelope (`test-only sink; no production entrypoint`), or `unknown` under a bounded one. Artifacts that escape the repository path are quarantined and never analyzed or fixed (they show as `[quarantined] … artifact path escape`).

## Tier-2: remediation

Tier-2 is opt-in. It only ever touches autofix-eligible findings; ineligible findings are reported and never remediated (no patch is generated for them). Eligibility is decided by policy (gate G3) — by default only `exploitable` is eligible; `production-reachable` requires an explicit policy override (see the policy section below).

### Local fix loop

`codna secure --fix --engine local` runs a local detect → fix → verify → re-prove-closure loop with no external engine and no SAST scanner image. Reachability and closure both come from the bounded local reference engine; the patch comes from the Codna agent (model from `CODNA_FIX_MODEL`).

```bash
codna secure . \
  --from-sarif results.sarif \
  --engine local --fix \
  --verification codna-security.yaml   # supplies the build/test commands
```

For each eligible finding, in an isolated ephemeral worktree pinned to the scan commit:

1. **Detect** — re-classify reachability with the bounded local reference engine.
2. **Fix** — generate a patch with the Codna agent.
3. **Integrity** — run the anti-evasion check (G4) before the patch is ever applied; a rejected patch is never applied.
4. **Verify** — apply the patch and run the manifest's build + test commands.
5. **Re-prove closure** — independently re-prove the original obligation is `closed`.

A finding is reported `REMEDIATED` only when the patch applied cleanly, passed integrity, did not regress the tests, and the obligation re-proves `closed`:

```
codna: remediating eligible findings with the Codna agent (local engine) …

✓ local fix: 2 eligible finding(s) processed
  [production-reachable] sql-injection  REMEDIATED — closure=closed, tests pass
  [production-reachable] command-injection  blocked: obligation not closed (closure=open)
  remediated: 1/2
```

Other per-finding statuses you may see: `blocked: patch integrity (<reason>)`, `blocked: tests failed (closure=<status>)`, and `no tests configured` (printed instead of "tests pass" when the manifest carries no test commands, since `tests_passed` is then `None`).

{% hint style="info" %}
`--engine local --fix` opens no PR: it proves the fix in an isolated worktree pinned to the scan commit, then applies the verified diff to your local checkout with `git apply` and re-runs verification there. Opening a PR requires the privilege-separated writer and a scoped token; passing `--open-pr` together with `--engine local` is refused.
{% endhint %}

### Closure is a separate judgment from reachability

This is a deliberate, load-bearing distinction.

{% hint style="warning" %}
**Closure is not the same as eliminating reachability.** A finding is `closed` when the security obligation is discharged — for example, a recognized sanitizer or bound-parameter query is added at the sink. The sink can stay production-reachable and the obligation still be closed. Codna does not require "all reachability gone"; it requires the obligation to be independently re-proven `closed`.
{% endhint %}

The local engine's closure proof is a bounded heuristic:

* The sink file must be in the patch's changed paths. If untouched, closure is `open`.
* A recognized barrier must appear in the added lines: a parameterized / bound-parameter query (`.execute(<sql>, (params))`), `shlex.quote`, `html.escape`, `bleach.clean`, a prepared statement / placeholder / `bindparam`, or an escape/sanitize call.
* Sink touched but no recognized barrier added → conservatively `open` (e.g. the sink merely moved).
* Empty diff or no primary sink location → `unknown`.

## The PR-open gate

A draft PR opens only on the logical-AND of nine conditions (`G1`…`G9`). A single failure blocks the PR, and the failing condition is named in the report. The gate is pure logic — it composes already-computed verdicts and never executes anything itself.

Expand each gate for the exact condition and what blocks the PR:

<details>

<summary>G1 — Immutable provenance</summary>

Blocks the PR when provenance is incomplete or any digest is unbound (`incomplete/unbound provenance`).

</details>

<details>

<summary>G2 — Baseline reproduction</summary>

Blocks the PR when the finding cannot be reproduced on the exact unpatched snapshot.

</details>

<details>

<summary>G3 — Policy-eligible proof</summary>

Blocks the PR when the verdict is `unreachable` / `unknown`, or eligibility is not granted by policy.

</details>

<details>

<summary>G4 — Patch integrity (anti-evasion)</summary>

Blocks the PR when the patch weakens verification or escapes the permitted change scope. This check runs before the patch is ever applied.

</details>

<details>

<summary>G5 — Regression safety</summary>

Blocks the PR when the build fails, tests fail, or the risk-simulation verdict is below the threshold.

</details>

<details>

<summary>G6 — Scanner confirmation</summary>

Blocks the PR when the scanner still reports the finding, or the patched scan is degraded versus baseline.

</details>

<details>

<summary>G7 — Independent closure proof</summary>

Blocks the PR when `closure_status` is not `closed`.

</details>

<details>

<summary>G8 — No alternate or new vulnerability</summary>

Blocks the PR when an equivalent alternate path remains, or the patch adds a new policy-blocking finding.

</details>

<details>

<summary>G9 — Attested handoff, base unchanged</summary>

Blocks the PR when the signed attestation fails verification, or the base moved before open.

</details>

```
✓ remediation: 2 eligible finding(s) processed
  [exploitable] a1b2c3d4e5f6g7h8i9j0…  opened https://github.com/acme/app/pull/482
  [exploitable] 0987654321fedcba0fed…  blocked: G6,G7
```

Without `--open-pr`, a finding that passes every gate prints `would open (report-only)` instead of opening anything.

{% hint style="info" %}
**G6 and G7 are different checks.** G6 is about the *scan* — the originating scanner confirms the finding is gone under an identical, non-degraded configuration (no quietly-dropped rules, files, or queries). G7 is about the *obligation* — an independent closure proof, satisfied by a sanitizer even while the operation stays production-reachable. Both must pass independently.
{% endhint %}

### Privilege separation behind the gate

The orchestration brain (`run_secure`) holds no proof, sandbox, or GitHub logic. It delegates to three privilege-separated collaborators:

* **Engine** — independent reachability and closure proofs (the authority).
* **Worker** — runs untrusted code (baseline scan, patch-gen, build/tests, scanner rerun) in a sandbox with no write token, and emits a signed attestation.
* **Writer** — cannot execute repository code; it independently re-verifies the attestation, the patch digest, and that the base is unchanged, then opens the draft PR with a narrowly-scoped token.

There is exactly one verified finding per PR.

## End-to-end: open a fix PR

```bash
export CODNA_API_KEY="ck_…"             # Codna key
export GITHUB_TOKEN="ghp_…"             # write scope, only consumed by the writer

codna secure . \
  --from-sarif results.sarif \
  --verification codna-security.yaml \
  --open-pr \
  --github-token "$GITHUB_TOKEN" \
  --repo-slug acme/app \
  --base-branch main
```

`--open-pr` (and remote `--fix`) require a `--verification codna-security.yaml` manifest pinning the scanner configuration and the build/test commands. For `--open-pr` the manifest must additionally be *resolved* (see the manifest section). The `repo` argument must be a local checkout — remediation reads the working tree and pins to the SARIF's commit.

### Two-job CI handoff

So that the write token never lives in a step that runs repository code, the worker and writer can be split across two jobs. The worker emits a signed evidence bundle (`attestation.json` + `patch.diff` + `finding.json`); a separate writer-domain command verifies it and opens the PR:

```bash
codna secure-open-pr \
  --evidence ./evidence \
  --repo-slug acme/app \
  --base-branch main \
  --github-token "$GITHUB_TOKEN"
```

```
✓ opened draft PR: https://github.com/acme/app/pull/482
```

The writer verifies the attestation signature against the shared `CODNA_ATTESTATION_KEY` and re-checks `digest_of(diff) == patch_digest` before it will open anything. If verification fails, no PR is opened.

## Expected result

Tier-1 always returns a per-finding verdict and never writes code. Tier-2 writes only after the finding is policy-eligible, the patch passes integrity checks, verification commands pass, closure is independently re-proven, and the writer verifies the signed evidence bundle. If any gate fails, Codna reports the blocking gate and does not open a PR.

## The verification manifest (`codna-security.yaml`)

The manifest is the reproducible, digest-bound plan that replaces raw shell flags. The whole document is bound by one digest, so the baseline and patched phases provably run the *same* configuration — change any field and the digest flips and the gate aborts (`MANIFEST-TAMPER`). It is loaded with PyYAML if installed, else parsed as JSON.

{% code title="codna-security.yaml" lineNumbers="true" %}

```yaml
scanner:
  id: semgrep
  image: returntocorp/semgrep@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
  command: ["semgrep", "--config", "p/security-audit", "--sarif", "-o", "out.sarif"]
  output: out.sarif
  accepted_exit_codes: [0, 1]      # 1 = findings present, still a clean run
  rules_digest: "sha256:fedcba…"   # pins the rule pack
  configuration_digest: "sha256:abc123…"

verification:
  build:
    - ["pip", "install", "-e", "."]
  tests:
    - ["pytest", "-q"]

sandbox:
  network: deny          # must be 'deny' or 'none' for --open-pr
  timeout_seconds: 1800
  cpu_limit: 4
  memory_mb: 8192

policy:
  autofix_classifications: ["exploitable", "production-reachable"]
  block_new_severities: ["high", "critical"]
  severity_overrides:
    sql-injection: critical
```

{% endcode %}

`scanner.id`, `scanner.command`, and `scanner.output` are required; everything else has a default. `--open-pr` additionally requires a **resolved** manifest, enforced before any work begins:

* `scanner.image` pinned by `@sha256:<64-hex>`,
* `scanner.rules_digest` present,
* `sandbox.network` is `deny` or `none`,
* at least one `verification.tests` command.

## Autofix policy

The `policy` block encodes gate G3 (which verdicts may receive a fix PR), the severities that block a PR when newly introduced (G8), and scanner-severity overrides. It carries a deterministic `digest` so it is provenance-pinned (G1).

| Field                     | Default                | Meaning                                                                                                                                                                |
| ------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autofix_classifications` | `["exploitable"]`      | Verdicts that may be auto-fixed. Add `"production-reachable"` to opt in (the operator's explicit override). `unreachable` and `unknown` are never eligible regardless. |
| `block_new_severities`    | `["high", "critical"]` | New-finding severities that block a PR under G8                                                                                                                        |
| `severity_overrides`      | `{}`                   | Per-rule severity remapping applied during SARIF ingest                                                                                                                |

```yaml
policy:
  # Opt in to fixing production-reachable findings (records the override)
  autofix_classifications: ["exploitable", "production-reachable"]
```

With the default policy, a `production-reachable` finding reports `production-reachable requires an explicit policy override` and is not remediated. After the opt-in above it reports `production-reachable allowed by explicit policy override` and becomes eligible.

## Troubleshooting

<details>

<summary><code>codna secure needs --from-sarif &#x3C;results.sarif>.</code></summary>

`--from-sarif` is required. Point it at your scanner's SARIF output.

</details>

<details>

<summary><code>--open-pr needs --verification &#x3C;codna-security.yaml> …</code></summary>

`--open-pr` requires a manifest. Supply `--verification`.

</details>

<details>

<summary><code>--fix needs --verification … or use --engine local …</code></summary>

Remote `--fix` needs a manifest; for a scanner-less local fix, add `--engine local`.

</details>

<details>

<summary><code>SARIF provenance incomplete: …</code></summary>

Provenance (G1) failed. Common items: `no versionControlProvenance revisionId`, `revisionId … is not a full 40-hex commit`, `driver name missing`, `driver version missing`. Re-run the scanner so it records the full commit and driver. Only SARIF `2.1.0` is accepted.

</details>

<details>

<summary><code>manifest not resolved for --open-pr: …</code></summary>

The manifest is not fully pinned. Fix the listed items: pin `scanner.image` by `@sha256`, set `scanner.rules_digest`, set `sandbox.network: deny`, and add a `verification.tests` command.

</details>

<details>

<summary><code>cannot parse manifest …: PyYAML not installed and content is not JSON</code></summary>

Either install PyYAML or provide the manifest as JSON.

</details>

<details>

<summary><code>--open-pr needs the privilege-separated writer + a scoped token; `--engine local --fix` applies to the local checkout but opens no PR.</code></summary>

The local remediation lane applies the verified patch to your checkout but cannot open PRs. Use the privilege-separated writer flow for `--open-pr`.

</details>

<details>

<summary><code>--open-pr needs a write token: --github-token or $GITHUB_TOKEN.</code></summary>

Provide a write-scoped token via `--github-token` or `GITHUB_TOKEN`.

</details>

<details>

<summary><code>remediation needs a local repo checkout (pass a local path, not a URL).</code></summary>

`--fix` / `--open-pr` read the working tree. Pass a local path, not a git URL.

</details>

<details>

<summary><code>could not derive owner/repo from the git remote; pass --repo-slug owner/repo.</code></summary>

The origin remote is not a recognizable GitHub URL. Pass `--repo-slug owner/repo`.

</details>

<details>

<summary><code>set CODNA_ATTESTATION_KEY (shared with the worker) …</code></summary>

`secure-open-pr` needs the same HMAC key the worker signed with. Export `CODNA_ATTESTATION_KEY` in both jobs.

</details>

<details>

<summary><code>writer refused to open the PR: …</code></summary>

The writer's independent re-verification failed (attestation signature or `digest_of(diff) == patch_digest`). The PR is intentionally not opened.

</details>

{% hint style="success" %}
**The contract.** Every PR Codna opens is backed by a complete chain: bound provenance, a reproduced baseline, a policy-eligible verdict, an integrity-checked patch, a clean build/test run, scanner confirmation under an identical config, an independent closure proof, no new or alternate vulnerability, and an attested, signature-verified handoff. If any link is missing, Codna reports it and stops — it does not open the PR.
{% endhint %}

For the bug-fix workflow (failing tests, `--from-junit`, `--apply`) see the Fix page; for repository understanding and context reduction see the Triage page; for running Codna inside Cursor or Claude Desktop see the MCP page.

## Next steps

* [CLI Reference](/reference/cli.md) — every `codna secure` and `codna secure-open-pr` flag.
* [GitHub Action](/guides/github-action.md) — run secure mode in CI with the packaged action.
* [MCP Server](/guides/mcp.md) — expose read-only secure triage to Cursor or Claude Desktop.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.codna.ai/guides/security-autofix.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
