Skip to main content
Suppressions are not a weakness in the model — they’re the governance surface. Real repositories have false positives, accepted risk, and migration windows. Charter supports all of those. The question isn’t whether to suppress; it’s whether the suppression is intentional, documented, and bounded. An unbounded suppression mechanism creates two problems fast: teams stop fixing issues because muting is easier than review, and later reviewers cannot tell which risks were understood versus forgotten. Charter’s governance model is built to prevent both.

Two suppression mechanisms

.charter-suppress.yml is the repo-level governance file. It is the right choice when the finding has no precise line location, the target file cannot carry inline comments, or the team wants a central, reviewable suppression ledger.Generate an entry using charter suppress:
charter suppress --rule AE-CC-001 --reason "Claude config lives in the infra repo" --expires 90d --approver "@tashfiqul"
This writes a structured entry to .charter-suppress.yml:
suppressions:
  - rule: AE-CC-001
    reason: "Claude config lives in the infra repo"
    expires: "2026-09-07"
    approver: "@tashfiqul"
The expires field is stored as an absolute YYYY-MM-DD date. The CLI default is 90 days from today. Permanent waivers require expires: permanent and a mandatory approver field.Optional path field scopes the suppression to a specific file or glob, reducing the blast radius.

Three governance rules

Every scan audits suppressions through three dedicated rules:
RuleSeverityWhen it fires
AE-SUPPRESS-001MediumAny suppression entry is missing a reason: field
AE-SUPPRESS-002HighA permanent suppression (expires: permanent) has no approver: field
AE-SUPPRESS-003InformationalSuppression rate exceeds 30% of all findings (signal only, no score deduction)
AE-SUPPRESS-001 is the simplest rule in the model. Every suppression must explain itself. “False positive” alone is usually not enough. “Vendored test fixture” or “lives in a separate infra repo” is much better — it gives a future reviewer the context they would otherwise have to rediscover. AE-SUPPRESS-002 draws a hard line: permanent waivers require accountability. Without an approver, the underlying finding stays active and the accepted risk is treated as undocumented — regardless of how well-reasoned the suppression may be.

What suppression does to the score

Suppressed findings are excluded from the base score calculation entirely. They are listed separately in charter doctor output under a “Suppressed” section and appear in the HTML report with full detail. In SARIF output, suppressed findings carry a suppressed: true annotation so downstream security tooling can distinguish them from active findings.
This is why suppression governance matters so much: the mechanism directly changes the final score. Without an audit trail, a score of 95 could mean an excellent repo or a heavily-suppressed one. Charter makes both cases visible and distinguishable.

Expiry behavior

When a suppression’s expires date passes, the finding re-surfaces as active on the next scan. The suppression entry itself remains in .charter-suppress.yml but is ignored — Charter treats expired dates as if the suppression were never there.The expired entry stays in the file deliberately. It provides an audit trail: this finding was suppressed, it expired on this date, and it was not re-suppressed. That history is valuable for security reviews.To re-suppress, either update the expires field to a new future date or add expires: permanent (with a required approver field). Do not delete the old entry; amend it.
The CLI’s charter suppress command always sets a default 90-day expiry and stores it as an absolute date. That is the recommended path.Hand-authored entries in .charter-suppress.yml with no expires field are honored without a default TTL. Charter does not infer a 90-day window from the file’s last-modified time. If you write an entry by hand, the absence of expires means it has no expiry — which means it will also need an approver if it’s effectively permanent, or it will trigger AE-SUPPRESS-002.The clean path: use charter suppress for all new suppressions and let the CLI handle the date arithmetic.

When to suppress vs fix

Use suppression when the finding is a confirmed false positive in this specific repo, or when the risk is real but explicitly accepted with documented justification and a finite window. Do not use suppression as a substitute for fixing the issue when:
  • Charter can fix it safely → run charter fix
  • The fix is straightforward and low-risk → fix it manually
  • The finding is new and not yet understood → investigate first
A healthy suppression workflow:
1

Confirm the finding

Read the finding detail with charter explain <RULE-ID>. Verify that the finding is a real false positive or genuinely accepted risk in this repo — not just inconvenient.
2

Suppress with a meaningful reason

Run charter suppress --rule <ID> --reason "...". The reason should tell a future reviewer what is being accepted and why it is safe or necessary in this context.
3

Set a bounded expiry

Accept the default 90-day expiry unless you have a specific reason to change it. Permanent waivers are the exception, not the default.
4

Add an approver for permanent waivers

If expires: permanent is truly justified, add --approver "@handle". This is enforced by AE-SUPPRESS-002 — without it, the suppression is rejected and the finding stays active.
5

Let governance rules keep it honest

AE-SUPPRESS-001 and AE-SUPPRESS-002 run on every scan. They are not optional. They exist to ensure the suppression ledger stays trustworthy over time, not just at the moment of creation.