skip to content

In KICS, how is a built-in query identified, and how do you run only selected queries or skip others in a scan?

level: middleimportance: should knowfreq 13%

answer

  1. one folder per query
  2. the UUID in metadata.json
  3. include or exclude, never both
  4. -q replaces the default path
  5. experimental stays off by default

basics

~10 s

Each built-in query is a folder holding query.rego and a metadata.json whose id is a UUID; that UUID is what --include-queries and --exclude-queries take, alongside --exclude-categories, --exclude-severities, --type and --queries-path.

solid answer

~40 s

The library lives under `assets/queries/<platform>/<provider>/<query>/`: a `query.rego` plus a `metadata.json` holding the `id` UUID, `queryName`, `severity`, `category`, `platform` and `cloudProvider`. The UUID is the stable handle — it is the `query_id` in the JSON report and the rule `id` in SARIF. `-i, --include-queries` runs only the listed UUIDs; `--exclude-queries`, `--exclude-categories` and `--exclude-severities` drop queries before evaluation. Inclusion cannot be combined with `--exclude-queries` or `--exclude-categories`, and once an include list is set the exclusion filters are not consulted. `-t, --type` and `--cloud-provider` narrow by platform and provider, experimental queries need `--experimental-queries`, and `-q, --queries-path` replaces the default library path rather than adding to it.

code

json · 11 lines
json
{
  "id": "db0ec4c4-852c-46a2-b4f3-7ec13cdb12a8",
  "queryName": "CloudWatch Logs Destination With Vulnerable Policy",
  "severity": "LOW",
  "category": "Access Control",
  "platform": "Terraform",
  "cloudProvider": "aws",
  "cwe": "155",
  "oldSeverity": "MEDIUM",
  "riskScore": "4.6"
}

go deeper

for a junior

Recall that every KICS query is a folder with query.rego and metadata.json, and that its id UUID is what the selection flags and reports use.

for a middle

Explain the include-versus-exclude rules, which flag pairs KICS refuses, and why -q replaces the default library while -b merges libraries.

for a senior

Show how you keep a query selection reviewable in a config file under version control, and how you spot a selection that silently drops coverage.

for a principal

Weigh running the full library and triaging noise against curating an include list per repository, and who owns that list as the library grows.

## How the library is laid out KICS's checks are called **queries**. Each one is a folder in the query library, which ships under `assets/queries` and is grouped by IaC platform and, where it applies, by cloud provider: ``` assets/queries/ terraform/aws/cloudwatch_logs_destination_with_vulnerable_policy/ query.rego metadata.json ansible/aws/alb_listening_on_http/ k8s/... openAPI/3.0/... common/passwords_and_secrets/ ``` `query.rego` holds the detection logic in Rego, the policy language of Open Policy Agent. `metadata.json` holds everything that describes the check. The folder name is only a label; the identity lives in the metadata. ## What `metadata.json` carries | Field | Meaning | |---|---| | `id` | a **UUID** — the query's identity everywhere KICS refers to it | | `queryName` | the human-readable title shown in reports | | `severity` | `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, `INFO` (or `TRACE` for inventory queries) | | `category` | for example `Access Control`, `Encryption` or `Best Practices` | | `platform` and `cloudProvider` | which IaC technology and provider it applies to | | `oldSeverity` | the earlier rating, on queries re-rated in KICS 2.x | | `cwe`, `riskScore`, `descriptionID` | classification and description bookkeeping | The `id` UUID is what appears as `query_id` in the JSON report and as the rule `id` in SARIF, and it is what every selection flag takes. Names and folders can be reworded; a UUID in a pipeline config keeps pointing at the same check. ## Choosing which queries run | Flag | Takes | Effect | |---|---|---| | `-i, --include-queries` | UUIDs | run **only** these queries | | `--exclude-queries` | UUIDs | drop these queries | | `--exclude-categories` | category names | drop every query in these categories | | `--exclude-severities` | `critical`, `high`, `medium`, `low`, `info`, `trace` | drop queries of these severities | | `-t, --type` / `--exclude-type` | platform names | load only, or never, these platforms' queries | | `--cloud-provider` | `aws`, `azure`, `gcp` and others | load only these providers' queries | | `--experimental-queries` | — | also load queries not yet thoroughly reviewed (off by default) | Two combinations are refused outright: `--include-queries` with `--exclude-queries`, and `--include-queries` with `--exclude-categories`. KICS stops with an error saying the flags cannot be provided simultaneously. `--type` and `--exclude-type` are refused together in the same way. ## The order KICS applies the filters When the library loads, each query passes through these gates in turn: 1. Experimental queries are skipped unless `--experimental-queries` is set. 2. The platform must match `--type` (platform-independent `Common` queries always pass), and the provider must match `--cloud-provider` if one was given. 3. If an include list exists, the query loads **only if its UUID is on it**, and nothing else is checked. 4. Otherwise it is dropped if its UUID, category or severity is excluded — and `TRACE` queries are dropped unless `-m, --bom` asked for the bill of materials. Step 3 has a consequence worth knowing: `--include-queries` combined with `--exclude-severities` is accepted, but the severity exclusion is never consulted. ## Pointing KICS at a different library - `-q, --queries-path` defaults to `./assets/queries` and **replaces** that list: pass only `./team-queries` and the built-in library is not walked at all. List both directories to add rather than replace. - `-b, --libraries-path` is different: it holds shared Rego helper functions as `<platform>.rego`, and those **merge** with the default libraries, a same-signature function overriding the built-in one. - `--input-data` points at a folder of `<query UUID>.json` files that override the keys of a query's `data.json`, for queries that ship one, so a built-in list can be tuned without editing the query. ## Making the selection stick Selections belong in version control, not in someone's shell history. Every flag can live in a configuration file — JSON, YAML, TOML or HCL — passed with `--config`, or in a `kics.config` at the root of a single scanned path, which is loaded automatically. Flags can also come from environment variables with a `KICS_` prefix, such as `KICS_EXCLUDE_QUERIES`. When the same flag is set twice, the command line wins over the environment, and the environment over the file. ## Checking what actually ran A selection is only as good as its effect, and the JSON report shows the effect. `queries_total` says how many queries loaded; comparing it with a run that uses no selection flags shows how much the filters removed. Each matched query appears with its `query_id`, `severity`, `category` and `platform`, so a reviewer can confirm that an excluded category really is absent and that a query on the include list really ran. Running with `--log-level DEBUG` adds a log line for every query excluded at load time.

  • How do you add a team's custom queries to a KICS scan without losing the built-in library?
    Pass both directories to `-q`, for example `-q ./assets/queries,./team-queries`, because `--queries-path` replaces the default list instead of appending to it. Shared Rego helper functions go in `-b, --libraries-path` as `<platform>.rego`; that flag does merge with the default libraries, and a function with the same signature overrides the built-in one.
  • How do you change a value a built-in KICS query keeps in its data.json, without editing the query?
    Create a folder holding a file named after the query's UUID, `<uuid>.json`, containing only the keys to change, and pass the folder with `--input-data`. KICS merges it over the query's `data.json`; keys you leave out keep their defaults, and each new value must have the same type as the original. Only queries that ship a `data.json` support this.

saying these in an interview costs you the question

  • KICS queries are selected by their human-readable query names.
  • -q adds a folder of extra queries on top of the built-in library.
  • --include-queries and --exclude-queries can be combined to fine-tune a scan.
  • Experimental queries run in every scan unless you exclude them.
  • The query folder name is the identifier the JSON report uses.