Guide 018 decision guide

When to suppress a finding and when to keep investigating

Decide when a security finding can be narrowly suppressed, when investigation must continue, and what evidence makes the decision reversible.

Suppress a scanner alert only when you can state which precise claim is being set aside, for which scope and revision, and what evidence defeats or deliberately accepts it. If a decisive control, deployment fact or consequence remains unknown, keep the claim under investigation with an owner and a next check. If a real issue is accepted for a time, record an authorized risk decision; do not label it a false positive. If the code is fixed, verify the fix at a new revision instead of hiding the old alert. These distinctions keep a quiet dashboard from becoming a false safety signal.

Suppression is a workflow action, not a technical proof. GitHub's code scanning documentation says dismissal removes an alert from the current count and can stop the same code from generating a future alert; it also records the reason and permits reopening. Other tools behave differently, so inspect your tool's exact semantics before applying a broad rule or bulk dismissal.

Choose the outcome before touching the suppression control

Use four questions in order:

  1. Is the claim factually wrong for this path? Verified counterevidence may justify a false-positive disposition. A sanitizer or ownership check counts only if this entry path necessarily uses it and it blocks the alleged effect.
  2. Is the claim true but outside the stated scope? A development-only dependency may be absent from a production artifact yet still matter to the build environment. A scope-specific exclusion is possible; a global “safe” label is not.
  3. Is the issue real but intentionally left open? That needs an accountable risk acceptance with reason, duration and review date, not a false-positive reason. A developer's “we cannot fix it this sprint” is not technical counterevidence.
  4. Is the fix verified? Close a real issue only after evidence shows the unsafe path is prevented or removed in the new revision. A merged pull request or disappeared alert alone does not answer this.

When none of these questions can be answered, keep investigating. NIST's SSDF, PW.7 describes human review and triage of tool issues in the development workflow. That review should record uncertainty, not force an answer for dashboard hygiene.

An illustrative redirect alert with two different routes

Illustrative example, not a customer finding: Larch Portal gets an open-redirect alert for GET /session/continue?next=.... The cited handler calls a redirect helper, and the alert says a visitor can make a trusted Larch link send another user to an arbitrary external site. That is a meaningful claim to check: OWASP describes how unvalidated redirect inputs can send users to a malicious destination. A developer says, “That route has an allowlist; suppress the rule everywhere.”

The security engineer pins the revision, traces the exact route and inspects the deployed build. In this invented case, next is treated only as a key: home selects a fixed server-defined /home path, billing selects /billing, and every other value selects /home. The helper receives that selected path, never the caller's URL. A second reviewer confirms the resolver and route wiring in the assessed build. The constructed source facts select the fixed fallback for unknown keys; no requests were performed for this exercise. The source and deployment evidence defeats the arbitrary-external-redirect claim for this route and build; a few matching requests alone would not prove every possible input safe.

A separate invitation route, GET /invite/accept?return_to=..., reaches the same redirect helper through different code. Its input handling and deployed configuration have not been reviewed. The first route's alert may be dismissed narrowly, with its evidence, while the invitation route remains under investigation. A global suppression on the helper or rule would conceal that second question.

The decision record should be as specific as the evidence:

Field Larch Portal entry
Original claim A visitor can choose an external destination through GET /session/continue?next=....
Bound scope That GET route at revision lp-72 in assessed deployed build LP-72; invitation flow excluded.
Counterevidence The deployed route passes the input through a fixed key-to-path map; unknown keys fall back to /home. The exercise assumes checked route wiring; actual independent review and controlled requests are not reported.
Decision Dismiss this route-specific alert as a false positive. Do not suppress the redirect helper or weakness rule globally.
Open question The invitation route uses the helper through another path; its return_to validation is unverified.
Owner and next check Identity-flow owner supplies the invitation route's deployed configuration and input path; AppSec reviews it before disposition.
Reopen trigger Resolver, route wiring, fallback behavior or build changes; new evidence of a bypass.

This is a review example, not proof that a given scanner supports route-scoped dismissal. If the tool only offers a global ignore rule, keep the alert visible or manage a separate scoped decision record until a safe configuration is available. The lack of a fine-grained button is a tooling constraint, not a reason to broaden the conclusion.

Calculate what the suppression would hide

Use a fictional matching model to inspect collateral effects. These options are illustrative, not promises about any scanner. The candidate set is:

  • S1: reviewed session-continuation route, resolver lp-72, fixed destinations.
  • I1: unreviewed invitation route using the same helper/file.
  • S2: session route after resolver lp-73 changes its fallback to a request-supplied destination.
Proposed matching scope S1 hidden? I1 hidden? S2 hidden? Decision
Exact claim plus checked control revision lp-72 Yes No No Fits the evidence if the real tool can express and preserve this boundary.
Helper/file pattern Yes Yes Yes Reject: hides an unreviewed caller and changed control.
Entire open-redirect rule Yes Yes Yes Reject: discards unrelated coverage as well.

Do not assume an “alert fingerprint” includes the control revision. Some identities deliberately survive source movement or changes. Inspect the matching implementation or documented semantics. In particular, GitHub documents that dismissal applies across branches; a revision-specific review note does not automatically make the product action revision-specific.

If the available tool cannot distinguish S1 from S2, keep the alert visible with a linked disposition, or use a separately reviewed workflow that reliably invalidates the dismissal when the resolver changes. A calendar reminder alone is weak if changes can occur between reminders. The fallback record should say: claim rejected at lp-72; broad tool suppression declined; reassess on resolver change. That gives the team a truthful status without sacrificing future visibility.

When lp-73 arrives, compare the decisive property: unknown keys no longer select a fixed server path. The old counterevidence has expired. Open an investigation for the changed route and inspect the new destination handling; do not label it verified solely because the earlier defense disappeared. The history keeps its valid lp-72 rejection, while the current queue reflects a new question.

This small matching exercise is worth doing before every proposed bulk ignore: enumerate a reviewed case, an unreviewed sibling and a changed-control case, then identify exactly which each configuration conceals.

Review a suppression like a change to the assessment

A suppression changes what future reviewers can see. Treat its scope as part of the assessment configuration, alongside enabled rules and excluded files. The owner should be able to explain both the work it removes and the detection opportunity it could remove. In Larch, suppressing S1 saves repeated review of a fixed destination map; suppressing the helper could also hide I1, whose destination handling is unknown.

Before applying a change, write the expected matching behavior in ordinary language. “Hide the same reviewed session-route claim while the fixed resolver remains unchanged” is a useful objective. Then compare that objective with the actual tool mechanism. If the mechanism keys only on a file or rule, the mismatch is visible before the change reaches the team.

A manual preview can enumerate representative records without exercising the application: the reviewed alert, an unreviewed sibling, a changed fallback and a separate redirect elsewhere. Record which would disappear under the proposed filter. This is a configuration review, not proof of scanner detection quality. Its purpose is to prevent an obvious scope mismatch.

Decide what happens when the reason expires

A review date and a technical invalidation trigger do different jobs. The date catches stale decisions that have not been revisited; a resolver change can invalidate the reason immediately. Name who monitors the trigger and how the alert returns to attention. If the tool cannot detect that change, use a process that makes the dependency visible to code reviewers and disclose the remaining limitation.

An expired exception for an accepted issue should not silently become a false positive. It should return to the responsible owner's decision process with the original evidence and current exposure. Similarly, an expired false-positive review does not automatically prove the issue is real. It means the team must establish whether the defeating fact still applies.

For Larch, the expiry note might say: “The lp-72 map is the basis for rejection. Before adopting a resolver change, compare destinations and fallback behavior; if they differ, re-open investigation and restore alert visibility.” That is more precise than “review annually,” because it names the change that can invalidate the claim now.

If restoring visibility produces a large queue, preserve the separation between volume and truth. Prior decisions may still be reusable, but they must be matched to their actual control facts. A bulk suppression rollback is not evidence that every restored alert is a vulnerability. The review task is to identify changed assumptions and prioritize their reassessment, while keeping credible containment or low-risk repairs available.

Make suppression reversible and narrow

Every suppression should include the alert fingerprint, rule version, affected repository or artifact, immutable revision or version range, reason category, evidence references, approver, creation date, expiry or review trigger, and a link to the original claim. Avoid inline source comments containing secrets or private evidence. A repository-wide ignore should be exceptional and reviewed for collateral coverage loss. Before merging a suppression change, ask: which future alerts will this rule hide? If you cannot answer, reduce its scope or do not merge it.

Recheck suppressions after a rule update, framework upgrade, changed build recipe, new deployment path, or new evidence about the alleged weakness. A dismissal timeline is useful because it lets the next reviewer reconstruct the decision. GitHub's documentation supports a comment and reopen path; your local process should preserve equivalent context even when the tool lacks it.

Choose a failure response for an expired suppression. An expiry date that nobody observes has little operational value. The assigned owner should review whether the defeating control and scope still apply, then renew with evidence, remove the suppression or keep the claim under investigation. If the tool cannot enforce expiry, the team's existing review process must make the pending decision visible.

Check the unsuppressed view when evaluating a proposed rule change. A narrow fixture exception may be appropriate for the known synthetic value while an adjacent real credential must remain visible. This comparison needs representative authorized examples and the actual tool semantics; the article's illustrative decision record is not evidence that a particular suppression configuration preserves detection coverage.

If you have no trustworthy evidence for an alert today, the useful action is to name the missing artifact and owner, then set a near review date. Use the repeatable review workflow to obtain that evidence, and the rejected-claims history guide to keep prior decisions available without confusing them with open work.