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

# Suppressing Findings

> Mark investigated false positives as ignored — with a reason — so they stop adding noise without losing the audit trail.

When a scan surfaces a finding you've investigated and confirmed is a false
positive *for this project*, suppress it — **with a written reason** — so it
stops adding noise. Suppressed findings are hidden, not deleted: the reason
travels with the code and the audit trail stays intact.

## `.rafter.yml` ignore rules

Add an `ignore:` list to your project's [`.rafter.yml`](/guides/agent-security/policy-file).
Each rule names the file path(s), optionally the specific rule(s), and a
`reason`:

```yaml theme={null}
ignore:
  - paths: ["tests/fixtures/**", "src/legacy/config.py"]
    rules: ["AWS Access Key ID"]     # omit `rules` to suppress every finding on those paths
    reason: "fake test keys — no live path"
  - paths: ["docs/**"]
    reason: "documentation examples"
```

| Field    | Required | Notes                                                                                                                                                                    |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `paths`  | **yes**  | Glob(s). Matched anywhere along the absolute file path — `tests/fixtures/**` matches `/home/you/app/tests/fixtures/x`. A rule with no `paths` is skipped with a warning. |
| `rules`  | no       | Rule name(s) to suppress, matched **case-insensitively**. Omit to suppress *every* rule on those paths. A name that matches nothing is harmless.                         |
| `reason` | no       | Free text — your justification. Surfaced verbatim in the output, so write the proof.                                                                                     |

Rules are evaluated top-to-bottom and the **first matching entry wins**, so put
more specific entries first. Because `.rafter.yml` is committed to your repo,
the suppression (and its reason) persists across scans and travels with the
code.

<Note>
  Match `rules` on the finding's **rule name** (e.g. `"AWS Access Key ID"`) — the
  exact string shown as the `rule` in the scan JSON / SARIF. Not sure of the
  name? Run `rafter agent scan --json` and copy the `rule` field from the
  finding. Don't use a hashed `R-…` id from a PR comment; those are display-only
  and won't match.
</Note>

## What suppression does to a scan

On a local scan (`rafter scan`), suppressed findings move into a `_suppressed[]`
array in `--json` output, so you can still see exactly what was hidden and why:

```json theme={null}
{
  "results": [ /* findings still in play */ ],
  "_suppressed": [
    {
      "file": "/abs/path/tests/fixtures/fake.env",
      "line": 3,
      "column": 7,
      "rule": "AWS Access Key ID",
      "severity": "critical",
      "reason": "fake test keys — no live path",
      "source": ".rafter.yml"
    }
  ]
}
```

Suppression **never changes the exit code** — `rafter scan` exits non-zero only
when a *non-suppressed* finding remains. A clean run stays green, and your
diligence stays on the record.

<Info>
  `.rafter.yml` `ignore:` rules are applied by the **local scanner** (`rafter
    scan`, the pre-commit hook, CI). For findings from a **hosted scan** (`rafter
    run`) or shown in the dashboard, ignore them from the dashboard — those ignores
  are tied to the repo and persist the same way.
</Info>

## Baseline — adopting on a noisy repo

To start using Rafter on a codebase that already has findings, snapshot the
current state and only surface *new* findings from then on:

```bash theme={null}
rafter agent baseline create   # snapshot today's findings as the baseline
rafter scan --baseline         # subsequent scans show only NEW findings
```

The baseline lives at `~/.rafter/baseline.json` and is applied only when you
pass `--baseline`.

## `.rafterignore` (legacy)

A plain `.rafterignore` file — one glob per line — is still honored for
path-based suppression. Prefer `.rafter.yml` `ignore:`: it carries per-rule
scoping and a `reason`.

## When *not* to suppress

Suppress only a genuine false positive for this context, with a reason. Don't:

* comment out or delete a rule globally,
* broaden a suppression beyond the specific file/context,
* drop the scan from CI.

If a finding is real but you can't fix it yet, track it — don't bury it.
