Skip to main content
Status indicator: Under construction — coming soon

Suppressing noise — .wcagignore and false-positive dismissals

Not every finding needs a fix. Third-party component libraries, known audit-misfires, and out-of-scope routes all generate noise. Two complementary tools let you suppress it cleanly without hiding real issues.

The two suppression layers

Suppression mechanisms comparison
FileGranularityWhen to use
.wcagignorePattern-based (gitignore-style) — broad. Manually authored. Checked into git.Whole categories of noise: third-party libraries, entire routes, rule families you've decided not to enforce.
.wcag-audit/false-positives.jsonPer-finding (rule + selector + primary class) — narrow. Written by wcag-audit dismiss. Persists across scans.One-off false positives on a specific component you've verified is genuinely accessible.

.wcagignore syntax

Create a .wcagignore file at your project root. The format is similar to .gitignore: one pattern per line, comments with #, blank lines ignored.

Pattern types

.wcagignore pattern syntax reference
PatternMatchesExample
bare glob (no prefix)CSS class namescl-* suppresses all findings on elements whose primary class starts with cl-
class:<glob>CSS class names (explicit)class:foo-bar suppresses findings on .foo-bar elements
selector:<glob>Full CSS selectorselector:*.cl-* suppresses any element matching the selector pattern
route:<glob>URL pathroute:/admin/* suppresses all findings on admin routes
rule:<glob>Rule IDrule:focus-obscured-* suppresses all focus-obscured rule variants

Multi-token AND matching

Multiple tokens on a single line are treated as AND conditions. A finding must match all tokens on the line to be suppressed.

text
# Suppress focus-obscured only on /admin routes (AND)
rule:focus-obscured route:/admin/*

Example .wcagignore file

text
# ── Third-party libraries ──────────────────────────────────────────────────

# Clerk auth components (we don't own these)
class:cl-*

# Chakra UI and Material UI
class:chakra-*
class:MuiButton*
class:MuiInput*

# ── Routes we're not auditing ────────────────────────────────────────────────

# Admin panel — separate accessibility review process
route:/admin/*

# Storybook embedded previews
route:/storybook/*

# ── Rules we've intentionally scoped out ────────────────────────────────────

# motion-preference: we have a global prefers-reduced-motion stylesheet
rule:motion-preference-*

# ── Specific selectors ───────────────────────────────────────────────────────

# Legacy widget loaded via iframe — out of scope
selector:div#legacy-widget *

wcag-audit dismiss — per-finding false positive

Use wcag-audit dismiss when a single specific finding is a false positive but the rule itself, the class, and the route should continue to be audited normally.

bash
wcag-audit dismiss <rc-id> --reason "<substantive explanation>"
example
$ wcag-audit dismiss rc-abc123 \
  --reason "Button uses aria-label because visible text is a logo SVG; label is descriptive and tested with NVDA and VoiceOver"
✓ rc-abc123 dismissed — fingerprint saved to .wcag-audit/false-positives.json

How it works

  • Reason must be ≥ 20 characters. This prevents dismissals like "no" or "skip" from accumulating silently.
  • Writes a fingerprint to .wcag-audit/false-positives.json. The fingerprint is a SHA-1 hash of the rule ID + normalized CSS selector + primary class, so it remains stable even when page content changes between scans.
  • LLM fix-pass agents call this automatically when they investigate a finding, reproduce the element, and determine the audit is misfiring. The reason they supply is included in the JSON for traceability.
  • Surfaced in the next scan in a Previously marked false positives section of WCAG_FIXES.prompt.md — so a future agent can review dismissals and flag any that look wrong.
json
// .wcag-audit/false-positives.json (excerpt)
[
  {
    "rcId": "rc-abc123",
    "fingerprint": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
    "rule": "button-name",
    "selector": "button.logo-btn",
    "primaryClass": "logo-btn",
    "reason": "Button uses aria-label because visible text is a logo SVG; label is descriptive and tested with NVDA and VoiceOver",
    "dismissedAt": "2026-05-08T10:23:00Z",
    "dismissedBy": "user"
  }
]

When to use which

Decision guide for choosing suppression method
SituationUse
Whole third-party library (Clerk, Chakra UI, MUI Material) you don't own.wcagignore with a class: or selector: pattern
Entire route that's out of scope (admin panel, legacy pages).wcagignore with a route: pattern
One specific rule firing on one specific component you've verified is accessiblewcag-audit dismiss <rc-id> --reason "..."
A rule consistently misfiring on your own codeDismiss with reason, then file a bug so it can be fixed upstream
Entire rule family you've deliberately chosen not to enforce.wcagignore with a rule: pattern

What suppressed findings look like in the report

Suppressed findings do not silently disappear. Both .wcagignore matches and dismissed false positives appear in a dedicated footer section of the report and the prompt file. This means:

  • Reviewers can audit the suppression list during PR review to ensure nothing was suppressed inappropriately.
  • The count shown in CI output reflects actionable findings only, but the suppressed count is also reported so it's visible.
  • False positives dismissed with LLM agents include the agent-supplied reason, making it easy to verify the judgment was sound.
scan output with suppressions
✓ 47 routes audited
  Actionable findings:  3
  Suppressed (.wcagignore): 14  (8 class:cl-*, 6 route:/admin/*)
  Dismissed (false-positives.json): 2
  → See WCAG_FIXES.prompt.md for details