Skip to content
FendixDocumentationDocs

.fendix.yaml · SEC-001 · SARIF

Current release v3.7.0
GuideStablev3.7.0

Baselines and suppressions

Separate change detection from reviewed, reasoned suppression, one occurrence at a time.

On this page

How do I reduce repeat noise without hiding evidence?

Findings group occurrences

A finding in a report is a presentation group. When one check fires in several places, the report shows one finding with every location in affected_endpoints and every **occurrence** in occurrences, each with its own fingerprint. The finding's own fingerprint belongs to its primary occurrence, the location that sorts first.

Identity, baselines and .fendix-ignore act on occurrences. The engine suppresses first and groups the survivors afterwards, so a suppressed occurrence never shapes the endpoint, evidence or decision you see, and a production occurrence is never hidden because it would have shared a finding with a suppressed test fixture.

Use a baseline for change

A baseline answers what is new. An occurrence is new unless the baseline proves that exact occurrence was present when the baseline was saved. Adding a location to an existing finding reports only that location; removing a location never creates a new finding; moving code to another line does not make it new.

A baseline is not an approval and does not change intrinsic severity. --save-baseline writes baseline format v2, which records every occurrence.

terminal
fendix scan --code . --save-baseline baseline.json
fendix scan --code . --baseline baseline.json

Use .fendix-ignore for a reviewed exception

Every rule is applied to each occurrence and suppresses exactly the occurrences it matches. Give every suppression a concrete reason and, where possible, an expiry. Prefer the narrowest durable selector: an occurrence fingerprint, or a path pattern.

.fendix-ignore
ignore:
  # one durable occurrence identity
  - fingerprint: 4c701b3a3a1f3c118320a8ca99974d103287d459
    reason: "Accepted risk, JIRA-1234"
    until: 2026-12-01
  # test fixtures at any depth; production occurrences are still reported
  - endpoint: "**/tests/**"
    category: secrets
    reason: "Sample credentials in test fixtures"

Selectors and their scope

One selector decides each rule, checked in the order shown. When fingerprint or id is set, endpoint and category on the same rule are ignored and a warning is logged. Write separate rules instead.

fingerprint
One occurrenceDurable and preferred. For a grouped finding, copy the fingerprint of the occurrence you mean from occurrences.
id
The whole presented groupPositional SEC-NNN. It also covers occurrences added to that group later and can name a different finding after any change. Short-lived triage only.
endpoint (+ category)
One occurrenceMatches the occurrence's own path. With category, both must match.
category
Every occurrence in itVery broad. Use only when the whole category is out of scope.

Endpoint patterns

  • ** as a path segment matches zero or more directories: **/tests/** matches tests/a.py, pkg/tests/a.py and deeper paths.
  • * matches within one path segment: src/*.py matches src/app.py, not src/sub/app.py.
  • A wildcard pattern with no / matches a path segment at any depth, like .gitignore: *_test.py matches a/b/x_test.py.
  • dir/* and prefix* keep their historical prefix meaning.
  • A code location's :line is dropped before matching. A pattern equal to the full path:line pins that one line.
  • In METHOD /path, only the path is matched. Matching is case-insensitive, and \ in a pattern is treated as /.

Upgrading from v3.5.1 or earlier

Baselines saved by v3.5.1 or earlier still load, but they recorded groups, not occurrences. Each entry proves its own fingerprint and, at each exact recorded location, a finding of the same kind. Anything else is new. Re-save the baseline once with --save-baseline.

A fingerprint: rule copied from a grouped finding used to suppress the whole group; it now suppresses only the occurrence it names. **/ now also matches zero directories, and * no longer crosses /. Fendix v3 introduced the semantic fendix/v2 fingerprint; regenerate baselines and fingerprint rules created before v3.

Why does this work this way?

Read the exact identity boundary in Finding fingerprints. For governed release exceptions, use Decision Records and accepted risk and Release approvals. Exact baseline and ignore options are in the scan policy and history reference.