skip to content

In KICS, what do `kics-scan` comment directives do, and why does `# kics-scan ignore` inside a Terraform resource block have no effect?

level: middleimportance: nice to knowfreq 6%

answer

  1. comments that steer the scan
  2. file start versus anywhere
  3. ignore, enable, disable
  4. ignore-line and ignore-block
  5. JSON has no comments

basics

~20 s

kics-scan comments suppress results from inside the scanned file. ignore, enable= and disable= are file-level and work only above the first real line; ignore-line and ignore-block work anywhere, so an ignore inside a resource is disregarded.

solid answer

~40 s

A comment starting with `kics-scan` carries one of five commands. Three are file-level and must sit at the top of the file, above any real line: `ignore` skips the file, `enable=<uuid>,...` keeps results only for those queries, and `disable=<uuid>,...` drops results for them. Two work anywhere: `ignore-line` drops results on the comment and the line beneath it, and `ignore-block` drops results for the block that follows and all its keys. `# kics-scan ignore` inside a resource is a file-level command below a valid line, so KICS disregards it; `ignore-block` above the resource is what was meant. When directives collide, `ignore` beats `ignore-block`, then `ignore-line`, `enable` and `disable`. They work in Dockerfiles, Terraform HCL and YAML — not in JSON, which has no comments.

code

hcl · 10 lines
hcl
resource "aws_s3_bucket" "assets" {
  bucket = "assets.example.internal"
  # kics-scan ignore
  force_destroy = true
}

# kics-scan ignore-block
resource "aws_security_group" "legacy_bastion" {
  name = "legacy-bastion"
}

go deeper

for a junior

Recall that kics-scan comments exist, that ignore skips a file, and that ignore-line and ignore-block silence results next to the code.

for a middle

Explain which three directives must sit at the file start, what ignore-line and ignore-block cover, and the precedence order between them.

for a senior

Show that you know what directives cannot reach, such as JSON templates, and how -x with a similarity ID fills that gap and when it breaks.

for a principal

Weigh in-file exceptions that travel with the code against central exclusion lists that one team reviews, given that block-level directives silence every check.

## What a directive is KICS reads special comments in the files it scans. Any comment whose text starts with `kics-scan` is treated as a **directive** that changes which results KICS reports for that file. This lets an engineer record an exception next to the code it concerns instead of in a pipeline flag. The comment marker is the file's own, for example `#` in Terraform, YAML and Dockerfiles. Directives exist in KICS 2.2 for **Dockerfiles, Terraform HCL and YAML** — that is, Kubernetes manifests, Ansible playbooks, YAML CloudFormation and YAML OpenAPI documents. Any format without comments is out of reach. ## The five commands | Directive | Where it must sit | Effect | |---|---|---| | `ignore` | file start | skip the whole file | | `enable=<uuid>,<uuid>` | file start | report results for this file **only** from these queries | | `disable=<uuid>,<uuid>` | file start | drop results for this file from these queries | | `ignore-line` | anywhere | drop results on the comment line and the line beneath it | | `ignore-block` | anywhere | drop results for the following block and all its key-value pairs | The UUIDs are the `id` values from each query's `metadata.json`, the same values the JSON report prints as `query_id`. `ignore-line` and `ignore-block` take no IDs: they silence **every** query's results for their lines, not one check. ## Placement rules that trip people "File start" has a precise meaning: the directive must come before any **valid line** of code. Header comments may sit above it; a resource, a key or an instruction may not. - `# kics-scan ignore` written inside a `resource` block is below valid lines, so KICS disregards it and the file is scanned normally. The author almost always wanted `ignore-block` above the resource. - A `disable=` placed directly above the resource it was meant for is in the same position and has no effect either, unless nothing but comments precedes it. - For YAML, ignoring a whole resource with `ignore-block` requires the file to start with `---`, followed by the directive, followed by the resource. - In a Dockerfile, `ignore-block` covers the whole `FROM` stage that follows; the next `FROM` starts a block that is scanned normally. - In a Dockerfile, `ignore-line` above a multi-line instruction drops every line of that instruction. ## Precedence when directives collide KICS resolves conflicts in a fixed order: 1. `ignore` 2. `ignore-block` 3. `ignore-line` 4. `enable` 5. `disable` So a file that starts with both `disable=<uuid>` and `ignore` is skipped entirely, and an `ignore-block` silences a block even if `enable=` asked for one of the queries reporting inside it. ## Where comments cannot help JSON has no comment syntax, so a CloudFormation template, an OpenAPI document or a Terraform plan written in JSON cannot carry a directive. The command-line alternatives are: - `-x, --exclude-results` with a finding's `similarity_id` from the JSON report, which drops exactly that one result; - `--exclude-queries` with a query UUID, which drops that query everywhere in the scan. The similarity ID is a SHA-256 hash over the file's relative path, the query ID and the finding's search key and value. Renaming or moving the file therefore produces a new ID, and the excluded finding reappears. ## A worked example in YAML Ignoring one whole Kubernetes object needs the document separator first, then the directive, then the object: ```yaml --- # kics-scan ignore-block apiVersion: v1 kind: Pod metadata: name: debug-shell ``` KICS's documentation makes that leading `---` a requirement for ignoring a whole YAML resource, so a missing separator is the first suspect when the Pod's results still appear. The same pattern applies to an Ansible playbook or a YAML CloudFormation template when a whole resource should be skipped. ## Seeing what was suppressed The JSON report's `lines_ignored` counter records how many lines comment directives removed from evaluation, so a jump in that number after a merge is visible without reading every file. Whether a given exception should exist at all — its reason, approver and expiry — is a separate review question; the directive is only the mechanism.

  • How do you suppress one KICS finding in a JSON file, where no comment can be written?
    Take the finding's `similarity_id` from the JSON report and pass it to `-x, --exclude-results`, which drops that single result; `--exclude-queries` with the query UUID drops the query everywhere instead. The similarity ID hashes the file's relative path, the query ID and the finding's search key and value, so renaming or moving the file produces a new ID and the finding comes back.
  • What does `# kics-scan ignore-block` cover in a multi-stage Dockerfile?
    The whole `FROM` stage that follows the comment, and nothing more: the next `FROM` starts a block that is scanned normally. `ignore-line` above a multi-line instruction such as a long `RUN` drops every line of that one instruction.

saying these in an interview costs you the question

  • A # kics-scan ignore anywhere in a file skips the whole file.
  • ignore-block takes a query UUID and silences only that check.
  • kics-scan comments work in every file KICS scans, JSON included.
  • ignore-line hides results on the comment line only.
  • A disable= directive placed above a resource deep in the file applies to that resource.