A KICS scan of your repository passes, yet a Terraform file with a known misconfiguration produced no finding — what in KICS's report and defaults do you check?
answer
- was the file collected at all
- scanned versus parsed counters
- gitignore, size cap, config file
- tfvars, functions, custom modules
- suppressed, or just not counted
basics
~20 sWalk the pipeline: was the file collected (.gitignore, --exclude-paths, kics.config, the 5 MB cap, --type), parsed, evaluated (query filters, timeouts), resolved (tfvars, functions, custom modules), suppressed (kics-scan comments, -x), or merely not counted by --fail-on?
solid answer
~40 sI treat it as a pipeline and check each stage in the JSON report and the log. **Collected?** The root `.gitignore` is honoured by default, `--exclude-paths` may come from a `kics.config` or a `KICS_` environment variable, and files over `--max-file-size` (5 MB) are skipped with only a warning. **Parsed?** Compare `files_scanned` with `files_parsed`. **Evaluated?** Check `queries_total`, `queries_failed_to_execute` (each query has a 60-second `--timeout`) and any `--type`, include or exclude filters. **Resolved?** KICS resolves Terraform variables only from `terraform.tfvars`, `*.auto.tfvars` and defaults unless `--terraform-vars-path` is given, does not evaluate functions, and does not follow custom modules. **Suppressed?** `lines_ignored` counts lines dropped by `kics-scan` comments, and `-x` drops similarity IDs. Finally, the finding may be in the report while `--fail-on` keeps the exit status at 0.
code
bash · 2 lineskics scan -p ./infra -o ./kics-debug --exclude-gitignore -v --log-level DEBUG
jq '{files_scanned, files_parsed, queries_total, queries_failed_to_execute, lines_ignored, severity_counters}' ./kics-debug/results.jsongo deeper
Recall that a passing scan can still have skipped files, and that the JSON report records how many files were scanned and parsed.
Explain the defaults that remove files or values before evaluation: the root .gitignore, the 5 MB cap, kics.config, and the tfvars KICS resolves on its own.
Demonstrate a stage-by-stage triage from collection to exit status, using the report counters and the DEBUG log rather than guessing at the query.
Discuss how much of a green IaC gate's meaning depends on scanner limits like custom modules, and whether coverage evidence belongs in the gate itself.
## Treat the scan as a pipeline A green KICS job says only that nothing **counted** was found in what KICS **evaluated**. When a file you know is wrong produces no finding, the useful question is at which stage it fell out. KICS moves every file through the same stages — collect, parse, evaluate, resolve values, filter results, set the exit status — and each stage leaves evidence in the JSON report or the log. Rerunning with `-v --log-level DEBUG` and `-o` pointing at a scratch directory gives you both. Work from the first stage to the last: a file that was never collected cannot be fixed by tuning queries, and a finding that is in the report but did not fail the job is a gate problem, not a detection problem. ## Stage 1: was the file collected? Several defaults remove files before KICS even counts them: - **`.gitignore`.** Paths matched by the `.gitignore` at the root of the scanned path are excluded, and the log announces it. Generated directories and environment folders are often listed there. `--exclude-gitignore` turns this off. - **Configuration you did not type.** Flags come from the command line, then from `KICS_`-prefixed environment variables, then from a configuration file, in that order of precedence. A `kics.config` at the root of a single scanned path is loaded automatically, so an `exclude-paths` entry there applies to every run; when `-p` lists several paths it is not loaded unless `--config` names it. - **Size.** `--max-file-size` defaults to 5 MB. A larger file is skipped with a warning, not an error. - **Platform filters.** `-t, --type` or `--exclude-type` may have left Terraform out of the run. ## Stages 2 and 3: was it parsed and evaluated? | Report field | What a bad value means | |---|---| | `files_scanned` vs `files_parsed` | files that reached the parser but failed to parse, so no query saw them; the log names each one | | `queries_total` | fewer queries than a comparable unfiltered run means a `--type`, provider, include or exclude filter narrowed the library | | `queries_failed_to_execute` | queries that did not finish, typically after the per-query `--timeout` of 60 seconds | | `lines_ignored` | lines dropped by `kics-scan` comment directives | Also check the query itself: an `--include-queries` list that omits it, a `-q, --queries-path` that replaced the built-in library, an `--exclude-severities` value matching its severity, or an experimental query that needs `--experimental-queries`. At `DEBUG` level the log names each excluded query. ## Stage 4: could KICS see the value? KICS evaluates the source as written, with limited resolution: 1. **Variables.** Without help, KICS resolves only values from `terraform.tfvars` and `*.auto.tfvars` in the same directory, plus variable defaults. A value that lives in `envs/prod.tfvars` needs `--terraform-vars-path envs/prod.tfvars`, or a first-line comment `// kics_terraform_vars: envs/prod.tfvars` in the `.tf` file. 2. **Functions.** KICS does not evaluate Terraform functions or environment variables; an attribute built by a function stays a wrapped expression that a query may not recognise. 3. **Modules.** KICS understands only a list of official AWS registry modules kept in its `common.json` library and does not follow unofficial or custom modules. A dangerous value passed into a local module call is not joined to the resource inside the module, which is evaluated on its own with whatever default its variable carries. Scanning the Terraform plan JSON instead of the source sidesteps all three, at a cost that is its own decision. ## Stage 5: suppressed, or simply not gating? - A `kics-scan ignore-block` or `ignore-line` near the resource, or an `ignore` at the top of the file, removes its results; `lines_ignored` going up is the clue. - `-x, --exclude-results` drops specific findings by `similarity_id`, often from a list in a config file. - The finding may be **in the report** while the job stays green: `--fail-on` only counts the severities it lists, and `--ignore-on-exit results` or `all` returns 0 regardless. ## A quick triage order 1. Search the JSON report for the file name. If the finding is there, the problem is the gate, not detection. 2. Search the log for the file name: excluded, oversized or failed to parse. 3. Compare `queries_total` with a run using no selection flags. 4. Look for directives in the file and for `-x` entries in the configuration. 5. Check how the offending value reaches the resource: variable file, function or module.
- Why can a misconfiguration passed into a Terraform module call go unreported by KICS?KICS does not follow unofficial or custom modules; it understands only a list of official AWS registry modules kept in its `common.json` library. A value set in a `module` block for a local module is never joined to the resource inside it, and that resource is evaluated on its own with whatever default its variable carries. Scanning plan JSON is the usual workaround.
- Why might KICS miss the file only in CI, never on a laptop?Flags come from the command line, then `KICS_`-prefixed environment variables, then a configuration file. A runner may set `KICS_EXCLUDE_PATHS` or `KICS_TYPE`, and a `kics.config` at the repository root loads automatically for a single scanned path but not when `-p` lists several. Compare the runner's environment and command line, and rerun with `-v --log-level DEBUG`, which logs each excluded query.
saying these in an interview costs you the question
- A green KICS run proves every IaC file in the repository was evaluated.
- KICS resolves variables from any .tfvars file anywhere in the repository.
- A file over the size limit makes KICS fail with an error.
- An exit status of 0 means the KICS report contains no findings.
- KICS evaluates Terraform functions the same way the Terraform CLI does.