skip to content

Terrascan was archived in November 2025 — how would you move a Terrascan pipeline gate onto KICS without losing coverage or its suppressions?

level: seniorimportance: nice to knowfreq 4%

answer

  1. archived means a frozen library
  2. map rules by intent, not ID
  3. shadow run before the switch
  4. per-resource skips have no exact twin
  5. drift monitoring does not move

basics

~20 s

Run KICS in shadow beside Terrascan, map each Terrascan rule to a KICS query UUID by intent, translate every ts:skip into the narrowest KICS equivalent, then switch the gate with an explicit --fail-on list once coverage matches.

solid answer

~50 s

Tenable archived Terrascan on 20 November 2025, so its policies and parsers are frozen from then on. I would first inventory what it covered — Terraform, CloudFormation, ARM, Kubernetes, Helm, Kustomize, Dockerfiles — and note that KICS 2.2's documented platforms do not include Kustomize, and that Terrascan's monitoring of provisioned infrastructure has no KICS counterpart, because KICS only reads files. Then I run KICS beside it with `--ignore-on-exit results` and compare findings resource by resource. Rules map by intent, not ID: each Terrascan rule name becomes a KICS query UUID. A `ts:skip` skips one rule for one resource; the closest KICS equivalents are `-x` with that finding's similarity ID, or `ignore-block`, which drops every query's results for the block. Custom Terrascan Rego policies need rewriting against KICS's input. Finally I switch the gate with an explicit `--fail-on` list.

go deeper

for a junior

Recall that Terrascan is archived and no longer maintained, and that KICS is an open-source IaC scanner covering the same core platforms.

for a middle

Explain why rule identifiers do not carry over between scanners and which KICS forms replace an inline per-resource skip.

for a senior

Show a migration with a non-blocking shadow run, a per-resource comparison, suppression translation at the narrowest scope, and an explicit gate switch.

for a principal

Weigh a like-for-like port against using the migration to reset the rule set and suppressions, and who owns duties like drift that no scanner replaces.

## Why the move is not optional **Terrascan**, Tenable's open-source IaC scanner, was archived on 20 November 2025. Its repository is read-only and the project says it is no longer maintained. The binary keeps running, which is exactly the risk: its policy library, its parsers and its dependencies stop moving while providers, Kubernetes APIs and attack techniques keep changing. A gate built on it slowly turns into a check of yesterday's infrastructure. **KICS**, Checkmarx's open-source scanner, is a natural landing place because it covers the same core platforms and is also built on Rego, but "also Rego" is where the similarity ends. ## What carries over and what does not | Terrascan capability | KICS 2.2 equivalent | |---|---| | Terraform HCL, CloudFormation, ARM templates | `Terraform`, `CloudFormation` and `AzureResourceManager` platforms | | Kubernetes YAML and Helm v3 | `Kubernetes` platform; Helm charts are rendered and the Kubernetes queries run on the result | | Kustomize | not in KICS's documented platform list; scan the manifests an overlay produces | | Dockerfiles | `Dockerfile` platform | | monitoring provisioned infrastructure for drift | **none** — KICS only reads files | | policies as Rego with a JSON rule file | queries as `query.rego` with `metadata.json`, identified by UUID | | `ts:skip=<rule><reason>` inside a resource | no exact twin; see the suppression table below | The drift gap matters most: if a team relied on Terrascan to watch running infrastructure, that duty needs a new owner, because swapping scanners will not cover it. ## Step by step 1. **Inventory.** List the platforms scanned, the rules that ever fired, every `ts:skip`, every Kubernetes skip annotation, and any custom policies. 2. **Shadow run.** Add KICS to the same pipeline with `--ignore-on-exit results`, so it publishes reports without blocking while engine errors still turn the job red. 3. **Compare per resource.** For each Terrascan finding, find the KICS finding on the same resource. Record matches, KICS-only findings and Terrascan-only findings. 4. **Map by intent.** Build a table from Terrascan rule names to KICS query UUIDs. Identifiers never carry over; the misconfiguration they describe does. 5. **Close or accept gaps.** A Terrascan-only finding becomes either a known gap with an owner or a custom KICS query, which is query-authoring work. 6. **Translate suppressions** using the narrowest KICS form that matches each original. 7. **Switch the gate** with an explicit `--fail-on` list, update anything that parses the exit status for KICS's severity-coded values (60 for CRITICAL down to 20 for INFO), then remove Terrascan. ## Translating suppressions | Original intent | KICS form | Scope | |---|---|---| | one rule, one resource (`ts:skip`) | `-x` with the finding's `similarity_id` | exactly one result; a new ID if the file is renamed or moved | | one rule, one resource | `# kics-scan ignore-block` above the resource | **every** query's results for that block | | one rule, one file | `# kics-scan disable=<uuid>` at the file start | that query, the whole file | | one rule, everywhere | `--exclude-queries <uuid>` | that query, the whole scan | A `ts:skip` carried a reason inline. KICS's documented directive syntax has no reason field, so write the reason in an adjacent comment and keep the review of each exception wherever exceptions are reviewed today. ## Pitfalls - **Severity scales differ.** Terrascan severities and KICS severities are assigned by different maintainers; re-read the gate's blocking set instead of copying it. - **Custom policies do not port.** Both tools use Rego, but the input documents and the expected result shapes differ, so each custom policy is rewritten, not copied. - **Noise on day one.** KICS's library is large; triage its extra findings during the shadow period, or the switch floods teams and the gate gets bypassed. - **Kustomize overlays.** Build them in the pipeline and point `-p` at the output, which KICS reads as plain Kubernetes YAML. - **Report consumers.** Dashboards and scripts that parsed Terrascan's output need new parsers. KICS writes JSON by default and SARIF, JUnit, CSV, HTML and others on request through `--report-formats`, with each finding carrying `query_id`, `severity`, `file_name`, `line` and `similarity_id`. - **Version pinning.** Pin the KICS release and its container image in the pipeline, so the library does not change underneath a running comparison; upgrade deliberately once the switch is done.

  • How do you decide the KICS shadow run beside Terrascan is finished?
    When every Terrascan finding over a representative window is matched by a KICS finding on the same resource, accepted as a gap with a named owner, or shown to be a Terrascan false positive — and KICS's extra findings have been triaged so the switch does not flood teams. Elapsed time alone is not the criterion; the comparison table is.
  • What happens to the Kustomize overlays Terrascan used to scan?
    KICS 2.2's documented platforms do not include Kustomize, so scan what the overlay produces: build the manifests in the pipeline and point `-p` at the output, which KICS reads as plain Kubernetes YAML. Results then point at the built files, so keep a way to trace them back to the overlay that produced them.

saying these in an interview costs you the question

  • An archived scanner keeps working, so there is no reason to replace it.
  • Terrascan rule IDs can be passed straight to --exclude-queries.
  • kics-scan ignore-block is an exact equivalent of ts:skip.
  • Custom Terrascan Rego policies drop into KICS unchanged because both use Rego.
  • KICS can take over Terrascan's monitoring of provisioned infrastructure.