skip to content

Suppressing a Finding

A skip comment sitting in the very file under review lets the author clear the gate alone, so what that annotation must carry, and who ever reads it again, is the whole control.

on this pageshow

questions

4

A pull request adds an inline Checkov skip comment whose reason you cannot verify — how do you review it?

level: seniorimportance: must knowfreq 52%

answer

  1. the reason is a claim, not evidence
  2. rule bug or accepted risk?
  3. narrowest instrument available
  4. checkable in this diff or unfalsifiable
  5. who inherits the copy-pasted line

basics

~20 s

Review the skip as the change, not the comment: decide whether the finding is real or a rule bug, insist on the narrowest form, require a reason checkable in the same diff, and remember an annotation has no expiry and no approver.

solid answer

~40 s

I treat the skip line as the security-relevant part of the diff. First: is the finding true? If the resource really does the dangerous thing, this is an accepted risk; if the check misfires on a pattern the whole estate uses, it is a rule bug, and a per-resource skip is the wrong fix because every other team will hit it and write their own. Second: is this the narrowest form — an inline skip on the one block, not a config `skip-check` and not a path exclusion? Third: is the reason checkable *here*? "Bounded by the permissions boundary two files over" I can confirm in the diff; "this is safe" and "temporary" I cannot, and nothing expires an annotation. Fourth: who inherits it? A skip inside a shared module ships to every consumer.

go deeper

for a junior

Know that a skip line in a pull request is part of the change and deserves a question, not a rubber stamp. At minimum, ask what the reason means and whether the resource could simply be fixed instead.

for a middle

Be ready to separate an accepted risk from a misfiring rule, and to explain why the second one should be fixed in the rule rather than annotated in each repository that hits it.

for a senior

Demonstrate a repeatable review: is the finding real, is this the narrowest mechanism, is the reason checkable in this diff, and who inherits the line if it is in shared code. Name the three outcomes you would write.

for a principal

Own the trade-off between review friction and delivery speed. Be able to say which exemptions a team should self-serve in a comment and which must carry an owner and a date, and defend that line to both engineering and audit.

## The premise: the reason is a claim, not evidence The free-text reason on a suppression is written by the person who was blocked, is validated by nothing, and is read by one reviewer under time pressure. It is the weakest control in the pipeline, and it is also the last one. So the reviewer's job is not to read the reason and feel reassured; it is to work out what the reason would have to be true for, and whether any of that is checkable. ## Four questions, in order ### 1. Is the finding real? This is the fork that decides everything downstream, and it is the one candidates skip. - **The finding is true and the risk is accepted.** The resource does grant the wildcard, and there is a reason it must. A suppression is the right shape of answer; the argument is now about scope and duration. - **The finding is a false positive.** The check misreads a pattern that is actually safe here — and, crucially, is probably safe everywhere it appears. Then a per-resource skip is not a fix, it is a workaround that hides a rule bug. Every other team hits the same misfire, each writes their own skip with their own wording, and the estate accumulates dozens of annotations that all mean "the rule is wrong". The remedy is to narrow or correct the rule so nobody needs the skip. Asking "is this a rule bug or an accepted risk?" is the single highest-signal thing a reviewer can say here. ### 2. Is this the narrowest instrument? An inline annotation on the one violating block is the narrowest exemption available: one resource, one check id, visible at the site, gone when the resource is gone. If the diff instead adds an entry to the scan configuration that disables the check everywhere, or excludes a directory from scanning, the review bar is much higher — those excuse every future violation as well as this one, and leave nothing at the violating line for the next reader. ### 3. Is the reason checkable in this diff? Sort reasons into two piles. **Checkable here:** "the role is constrained by the permissions boundary attached three lines down", "this resource is destroyed by the same module's teardown", "see INFRA-4412" where the ticket is real and open. You can verify some or all of it without leaving the review. **Unfalsifiable:** "this is safe", "needed for the deploy to work", "temporary", "agreed with security". None of these can be checked, and two of them are actively misleading. "Temporary" is the one to challenge by name: an annotation has no expiry field, nothing re-evaluates it, and no report will ever say it has aged. In practice "temporary" means "permanent until somebody greps for it". "Agreed with security" is worth a single question — with whom, and where is that written — because if the agreement is real it can be pointed at, and if it cannot be pointed at, it is a claim about an absent third party. The practical ask is small: make the reason specific enough that a stranger reading it in two years can decide whether it still holds. That is the entire test, and it costs the author one sentence. ### 4. Who else inherits this line? Suppressions propagate by copy-paste better than almost anything else in a repository. A skip inside a shared Terraform module is delivered to every consumer of that module. A skip in a repository template is delivered to every repository created from it. A skip in the team's most-copied example file is delivered wherever people copy from. In all three cases the receiving team never made the judgment, never read the reason, and often does not know the line is there. So the reviewer question is: would I accept this line if it appeared, unexplained, in ten other repositories? If the answer is no, the exemption needs to be attached to something narrower than a shared file, or the module needs to stop producing the violation in the first place. ## Where the review ends There are only three outcomes worth writing down. **Approve** — the finding is real, the exemption is narrow, and the reason is specific and checkable. **Send back for a narrower form** — the mechanism is too wide, or the reason is unfalsifiable and can easily be made concrete. **Reject and ask for the fix** — the violation is straightforwardly fixable, and the skip exists because fixing it was slower than annotating it at five in the afternoon. One boundary to state rather than blur: if what this exemption genuinely needs is a named owner, an approver and a date on which it lapses, then a comment cannot carry any of that. That is a different instrument, and reaching for it is the honest answer when the risk is real but the acceptance should not be permanent or self-service.

  • The author says the skip is temporary. How do you hold that?
    By saying out loud that the annotation cannot expire — nothing re-raises it and no report will flag its age. So either the exemption moves to an instrument that can carry a date and an owner, or you accept it as permanent and review it on those terms. What does not work is approving 'temporary' as written and assuming someone will come back to it.
  • The author says the check is a false positive. Does that change your answer?
    Completely. A false positive is a defect in the rule, and a per-resource skip hides it. Every team that writes the same safe pattern will hit the same misfire and write their own annotation with their own wording, so the estate ends up carrying dozens of skips that all mean the rule is wrong. The fix is to narrow the rule.
  • The skip is being added inside a shared module. What is different?
    It is no longer one team's judgment. The annotation ships to every consumer of the module, into repositories whose owners never read the reason and may not know the line exists. Either the exemption belongs in the consuming repository where someone can own it, or the module should stop emitting the violating configuration.
  • How specific does the reason actually have to be?
    Specific enough that a stranger reading it in two years can decide whether it still holds. Naming the compensating control, the resource it depends on, or a ticket does that; 'this is safe' does not. It costs the author one sentence, and it is the difference between a suppression you can audit later and one you can only delete and re-argue.

saying these in an interview costs you the question

  • Reads the stated reason as evidence rather than an unverified claim
  • Approves because the pipeline is now green
  • Accepts temporary with no date, owner or ticket
  • Treats a misfiring rule as something a per-resource skip fixes
  • Waves through a repo-wide config skip as equivalent to an inline one
  • Ignores that a skip in a shared module ships to every consumer

context

open as a page

In Checkov, what does a #checkov:skip comment inside a Terraform resource block do?

level: juniorimportance: should knowfreq 58%

basics

~20 s

A checkov:skip comment suppresses one named check for the single block it sits inside. The form is checkov:skip=CHECK_ID:reason; the reason is free text nothing validates, and the finding is reported as skipped rather than failing the run.

open as a page

When should a Checkov exemption be an inline skip comment rather than a config-file skip-check or skip-path?

level: middleimportance: should knowfreq 45%

basics

~20 s

An inline skip fits one resource that legitimately violates one check: narrow, and visible in the diff. Use skip-check or skip-path only when the rule or path is wrong for the whole scan, since both are invisible at the violating line.

open as a page

How do you find every live Checkov suppression across your Terraform repos, and spot the stale ones?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

Collect two sources, not one: every inline skip annotation in the source, and every skip-check, skip-path and skip flag in scan configuration and pipeline definitions. Then age each one with git history and the scan's skipped-checks output.

open as a page