Two suppression mechanisms
- File suppression (.charter-suppress.yml)
- Inline directive (charter:ignore)
.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.yml: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:| Rule | Severity | When it fires |
|---|---|---|
AE-SUPPRESS-001 | Medium | Any suppression entry is missing a reason: field |
AE-SUPPRESS-002 | High | A permanent suppression (expires: permanent) has no approver: field |
AE-SUPPRESS-003 | Informational | Suppression 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.Expiry behavior
What happens when a suppression expires
What happens when a suppression expires
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.Hand-authored entries vs CLI-generated entries
Hand-authored entries vs CLI-generated entries
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
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.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.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.
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.