Skip to main content
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. Each rule names the file path(s), optionally the specific rule(s), and a reason:
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"
FieldRequiredNotes
pathsyesGlob(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.
rulesnoRule name(s) to suppress, matched case-insensitively. Omit to suppress every rule on those paths. A name that matches nothing is harmless.
reasonnoFree 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.
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.

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:
{
  "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 coderafter scan exits non-zero only when a non-suppressed finding remains. A clean run stays green, and your diligence stays on the record.
.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.

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:
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.