skip to content

Which Checkov behaviours silently narrow a scan of a repo holding Terraform, Helm charts and workflow files, so fewer resources get checked?

level: middleimportance: nice to knowfreq 17%

answer

  1. frameworks can drop out
  2. a missing system binary
  3. modules fetched elsewhere
  4. an allow-list of checks

basics

~10 s

Checkov drops the helm framework when no helm 3 binary is installed, skips registry and git modules unless --download-external-modules true is set, ignores .terraform, and runs only the listed checks when --check is used.

solid answer

~40 s

Start from `--framework`: it defaults to every framework, but `-f main.tf` narrows the runners to terraform and secrets, and `--skip-framework` or `--skip-path` remove more. The helm framework renders charts with the `helm` binary; if no helm 3 binary is on `PATH`, Checkov disables that framework with a one-line message and the charts' manifests are never checked. Terraform modules from a registry or git are not fetched unless you pass `--download-external-modules true`, and `.terraform` is ignored by default, so what `terraform init` downloaded is not read either. Finally `--check` is an allow-list: every check not named does not run and does not appear, including custom checks loaded with `--external-checks-dir` unless you add `--run-all-external-checks`.

go deeper

for a junior

Recall that Checkov runs per framework and that flags such as --framework, --check and -f decide what is scanned, not just how results are shown.

for a middle

Explain the specific silent drops: the helm binary dependency, undownloaded registry modules, the ignored .terraform folder, and --check as an allow-list.

for a senior

Show how you would audit an existing pipeline's real coverage with --show-config and the run summary before trusting its green history.

for a principal

Decide how coverage of the scanner itself is monitored over time, since a narrowed gate degrades without producing any failure signal.

## Why "fewer results" is a real failure mode A green Checkov run proves only that the checks which **ran** against the files that were **read** found nothing. Several defaults and flags shrink either side of that sentence without failing the job. In a mixed repository — Terraform, Helm charts, GitHub Actions workflows — it is common for a whole slice to drop out and nobody to notice for months. The cure is knowing where the drops happen and reading the run's summary for them. ## Frameworks: what Checkov decides to parse Checkov organises its parsers and checks into **frameworks**: `terraform`, `terraform_plan`, `cloudformation`, `kubernetes`, `helm`, `github_actions`, `dockerfile`, `secrets` and many more. - **`--framework`** defaults to all of them. Passing a list narrows the run, for example `--framework terraform kubernetes`. - **`--skip-framework`** removes named frameworks from the default set. - **`-f` / `--file`** filters runners by file type: pointing it at a `.tf` file runs only the terraform and secrets frameworks. - **`--skip-path`** removes paths by regular expression, relative to the working directory; word boundaries are not implicit, so `dir1` skips every directory named `dir1` at any depth. Each of these is legitimate. The trap is a pipeline that was narrowed once for speed and never revisited when new file types arrived: a job written as `--framework terraform` two years ago will not look at the Kubernetes manifests or the `.github/workflows` files added since, and nothing in its output says so. The summary only lists what ran, never what was left out. ## The helm framework needs a binary Checkov recognises a Helm chart by its `Chart.yaml`, renders it with `helm template` using the chart's default values, and then runs its Kubernetes checks over the rendered manifests. That rendering uses the real **helm binary**. If no helm binary of version 3 or later is on `PATH`, Checkov **disables the helm framework automatically** and prints that frameworks were disabled because of missing system dependencies. The run then behaves exactly like `--skip-framework helm`. The documentation explains why: it protects pipelines that pull the latest Checkov into an image that lacks helm. The cost is that a minimal CI image can skip every chart while the job stays green. ## Terraform modules that never enter the scan Checkov reads local modules referenced by path. Modules sourced from the Terraform registry or a git URL are different: 1. By default Checkov **does not download** them, so the resources they create are invisible. 2. `--download-external-modules true` fetches them into a `.external_modules` folder; `--external-modules-download-path` changes that location. 3. The `.terraform` directory that `terraform init` fills is on Checkov's default ignore list, together with `node_modules` and `.serverless`, so an initialised working copy does not help. 4. An experimental environment variable, `CHECKOV_EXPERIMENTAL_TERRAFORM_MANAGED_MODULES=True`, tells Checkov to reuse the modules Terraform already downloaded, for scans of the initialised root folder only. Private registries and repositories need credentials in environment variables such as `GITHUB_PAT` or `TF_REGISTRY_TOKEN` before the download can succeed. ## `--check` is an allow-list `--check` (`-c`) names the checks to run; **every other check is skipped and leaves no trace** in the output. A pipeline that started as `--check CKV_AWS_20,CKV_AWS_57` to trial two rules and was never widened runs two checks forever. Custom checks follow the same rule. `--external-checks-dir` loads extra checks from a directory and can be repeated; note that it **executes Python code** from that directory, so it should only point at trusted content. When `--check` is also present, a loaded custom check runs only if its ID is listed — unless you add `--run-all-external-checks`, which runs all external checks regardless of the allow-list, while still honouring `--skip-check`. `--external-checks-git` is the alternative source and cannot be combined with `--external-checks-dir`. ## Reading a run for coverage | Symptom | Likely cause | What to check | |---|---|---| | no helm results at all | helm framework disabled | the "disabled due to missing system dependencies" line; install helm in the image | | module resources missing | external modules not downloaded | add `--download-external-modules true` | | only a handful of check IDs in results | `--check` allow-list | the job's arguments or `.checkov.yaml` | | a directory absent | `--skip-path` or `-f` filtering | `--show-config` prints every setting and its source | `--show-config` is the quickest audit: it prints every argument and where it came from — command line, config file, environment variable or default. Pair it with a simple expectation test: a fixture directory holding one known-bad file per framework you rely on, which the pipeline must flag. If a framework drops out, the fixture stops failing and the change is visible the same day.

  • Where else can a narrowing setting hide if the CI command line looks clean?
    In a config file. Checkov reads `.checkov.yaml` or `.checkov.yml` from the scanned directory, or a file named with `--config-file`, and many flags also have environment variables such as `CKV_FRAMEWORK` and `CKV_CHECK`. `--show-config` prints the effective value of each setting and its source.
  • Why does Checkov warn you to use --external-checks-dir only with trusted directories?
    Custom checks can be Python classes, and loading them means importing and executing that Python inside the scanner process. A directory writable by an untrusted contributor would let them run arbitrary code in your CI job, with whatever credentials the job holds.

saying these in an interview costs you the question

  • If helm is missing, Checkov fails the run so the gap cannot go unnoticed.
  • Checkov reads the modules terraform init placed in .terraform automatically.
  • --check adds checks on top of the default catalogue.
  • Custom checks always run, whatever --check lists.
  • A green Checkov run proves every file in the repository was evaluated.