# Checkmarx KICS: scanning Terraform, Kubernetes and Ansible for misconfigurations with OPA

> KICS is an Apache-2.0 scanner that turns infrastructure-as-code files into a queryable document and runs Open Policy Agent rules against them. It is broad on platforms and thin on the operational details that decide whether a scan pipeline stays green.

**Checkmarx/kics** — Find security vulnerabilities, compliance issues, and infrastructure misconfigurations early in the development cycle of your infrastructure-as-code with KICS by Checkmarx.

- Repository: https://github.com/Checkmarx/kics
- Website: https://kics.io
- Stars: 2,710 · Forks: 385
- Language: Open Policy Agent
- License: Apache-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/checkmarx-kics

## What KICS scans, and the gap it fills

KICS stands for Keeping Infrastructure as Code Secure. The README describes it as finding "security vulnerabilities, compliance issues, and infrastructure misconfigurations early in the development cycle of your infrastructure-as-code." That sentence places it before deployment, not after. The target reader is the person who writes or reviews the Terraform module, the Helm chart, the Ansible role or the Kubernetes manifest, and who currently finds out about an open security group from a cloud audit rather than from a pull request.

The platform list in the README and docs/platforms.md covers Terraform, Kubernetes, Docker, CloudFormation, Ansible, Helm, OpenAPI, gRPC and Azure Resource Manager. That breadth is the actual selling point. A repository that provisions AWS with Terraform, deploys with Helm and configures hosts with Ansible would otherwise need three different linters with three different rule formats and three different output shapes. KICS reads all of them and emits one result set.

The second differentiator is the rule language. KICS queries are written in Rego and executed by Open Policy Agent, which the go.mod pins as github.com/open-policy-agent/opa v1.12.3. Rules are therefore plain text in the repository, reviewable in a pull request, and forkable when a policy does not match your organisation's standard. That matters more than it sounds: most scanner arguments are really arguments about whether you can change a rule without waiting for a vendor.

## How the engine parses IaC into something Rego can query

The pipeline has three visible stages. First, KICS parses each file into a normalised JSON document. The dependency list shows the parsers it carries: hashicorp/hcl and hashicorp/hcl/v2 plus hashicorp/terraform-json for Terraform, helm.sh/helm/v3 for charts, gopkg.in/yaml.v3 for Kubernetes and CloudFormation, relex/aini for Ansible INI inventory, emicklei/proto for gRPC definitions, and sosedoff/ansible-vault-go for encrypted Ansible content. Each format gets its own reader rather than a generic text match.

Second, the parsed document is handed to the embedded OPA engine together with the query set. Queries match on paths inside that document, so a rule about an S3 bucket's public access setting is expressed against a known field name, not against a regular expression over the source text. This is why KICS can report a line number and a resource name together.

Third, results are serialised. The go.mod lists gocarina/gocsv for CSV, johnfercher/maroto for PDF, tdewolff/minify for shrinking JSON output, and BurntSushi/toml for TOML. That spread of output formats tells you the intended consumers: a CI job that reads JSON, a human who wants a PDF attachment, a spreadsheet-driven audit. The repository also ships a Dockerfile whose runtime stage copies assets/queries, assets/cwe_csv and assets/similarityID_transition alongside the compiled binary, so the query set travels with the image rather than being fetched at scan time.

One structural detail worth noting: the Dockerfile itself contains lines commented "kics-scan ignore-line", which means the project scans its own build files with its own engine. That is a small but real signal about how the maintainers treat the tool.

## Installing KICS and running a first scan

The README points to kics.io and docs.kics.io for installation guidance, and the repository publishes a container image at hub.docker.com/r/checkmarx/kics. The Docker route is the one the repository itself demonstrates: docker-compose.yml mounts the working directory at /path/ and runs the scan subcommand against it.

```yaml
services:
  kics:
    platform: linux
    image: checkmarx/kics:${IMAGE_TAG:-dev}
    container_name: kics
    hostname: kics
    volumes:
      - ./:/path/
    command: scan -p /path/ -v
```

That block is the project's own compose file, with the build section removed. The two arguments that matter are -p, the path to scan, and -v, which raises verbosity. Mounting the repository read-only at /path/ keeps the scanner from writing into your working tree.

If you prefer a direct container run, the same shape applies: pass a path inside the container with -p and let the image's bundled assets/queries supply the rules. The image is built from checkmarx/git as its runtime base, which is why the container can also resolve remote sources through hashicorp/go-getter in the dependency list.

For a source build, the Makefile defines the targets. GOLINT is set to golangci-lint, TARGET_BIN defaults to bin/kics, and the build target compiles cmd/console/main.go with version and commit stamped into github.com/Checkmarx/kics/v2/internal/constants.

```bash
make build
./bin/kics scan -p ./infra -v
```

After either route, expect a findings list keyed by query, file and line, with severity attached. The documentation does not state a default exit code policy in the README, so check the CLI help before wiring the command into a gate that fails the build.

## Where KICS stops being the right tool

KICS reads files. It does not read your cloud account. A Terraform plan that KICS approves can still create an over-permissive role if the permissiveness comes from a variable supplied at apply time, or from a module version resolved after the scan. Nothing in the repository suggests runtime or state inspection, and the dependency list contains no cloud provider SDK beyond aws-sdk-go-v2, which is a Go library rather than an account reader. If your risk lives in drift between the repository and the deployed estate, a file scanner is the wrong instrument.

The second boundary is remediation. KICS reports. The README describes detection, not fixing, and there is no evidence of an auto-fix mode. Treating it as a tool that will clean up your manifests is a misreading of what it does.

The third is the query set itself. A broad platform list means uneven depth. The docs publish a query index, and the honest way to evaluate coverage is to open that index and count the queries that touch the resource types you actually deploy. A team running a narrow stack on one cloud may find that a more specialised checker has sharper rules for exactly those resources, even though KICS supports more formats overall.

Finally, there is the noise problem that every IaC scanner has and that the README does not resolve. The README documents no inline suppression comment, no baseline file and no ignore mechanism for KICS itself, apart from the "kics-scan ignore-line" marker visible in the project's own Dockerfile. That marker exists, so some suppression path exists, but the README does not explain it. Budget time to work out how your team will silence accepted findings before you enable the scan on every pull request.

## KICS versus Checkov: same job, different rule engines

Checkov is the comparison people search for, and the difference is architectural rather than cosmetic. Checkov's policy layer is built around Python-based checks, which means a team that already writes Python can add a custom rule without learning a new language, and the ecosystem of contributed checks reflects that lower barrier. KICS commits to Rego and Open Policy Agent instead. Rego is a declarative query language with its own mental model, and the payoff is that policies compose, that the same engine is used across every supported format, and that anyone already running OPA for admission control is working in one language rather than two.

The practical consequence: if your organisation has OPA experience, KICS fits an existing skill set and your custom rules live next to your admission policies. If your organisation writes Python and has never touched Rego, Checkov will feel closer to hand, and the cost of the first custom rule is lower. Both are open source scanners that read IaC files and emit findings; the choice is about which rule language your team will actually maintain, not about which one finds more in the abstract.

A second axis is packaging. KICS ships a single Go binary and a container image with the query set baked in, which suits air-gapped or heavily cached CI environments. That is a deployment property, not a detection property, but it decides how much work the rollout takes.

## Licence, upgrade cadence and the cost of staying current

KICS is Apache-2.0, which permits commercial use, modification and redistribution provided the licence and notices are preserved. For most adopters the practical question is not the licence text but the notice obligations if you fork the query set into your own repository. That is a question for your legal team, not for this article.

The release history shows a fast-moving project. v2.1.20 landed on 2026-03-03, v2.1.21 on 2026-07-30, and v2.2.0 on 2026-09-17. The last push to the default branch was on 2026-09-23. Two things follow. First, pinning matters: if you consume the container image, pin a digest rather than a floating tag, because the Dockerfile in the repository already pins its own base images by sha256 digest, which is a reasonable pattern to copy. Second, query updates arrive with releases, so a pinned version means a frozen rule set. Some teams will accept that for reproducibility; others will want to bump on a schedule to pick up new checks.

Building from source has its own maintenance surface. The go.mod declares go 1.26.2, and the Dockerfile defaults to checkmarx/go:1.27.0. The Makefile's build target depends on generate, which runs go generate ./... after go mod tidy, so a source build pulls in code generation as well as compilation. If you are not prepared to track Go toolchain versions, use the image.

## Conclusion

Adopt KICS if your repositories hold Terraform, Kubernetes manifests, CloudFormation, Ansible, Helm, Dockerfiles, OpenAPI or gRPC definitions and you want one Apache-2.0 binary that scans all of them with OPA queries you can read. Do not adopt it expecting a hosted service, a fix-it engine, or a scanner that understands runtime state: the repository documents a CLI, a container and CI examples, and nothing about automatic remediation. Before rolling it out, run the container against one real repository, confirm the query set covers the resource types you actually use, and decide how you will handle the findings that are intentional, because the README does not explain any suppression mechanism beyond a marker visible in the project's own Dockerfile.

## FAQ

### What is Checkmarx KICS?

KICS stands for Keeping Infrastructure as Code Secure. It is an open source scanner, published by Checkmarx under Apache-2.0, that finds security vulnerabilities, compliance issues and infrastructure misconfigurations in infrastructure-as-code files.

### How do I install KICS?

The README points to kics.io and docs.kics.io for installation, and the project publishes a container image at hub.docker.com/r/checkmarx/kics. The repository's own docker-compose.yml runs the image with the command scan -p /path/ -v against a mounted directory.

### Which platforms does KICS support?

The README and docs/platforms.md list Terraform, Kubernetes, Docker, CloudFormation, Ansible, Helm, OpenAPI, gRPC and Azure Resource Manager.

### What language are KICS queries written in?

KICS queries are written in Rego and executed by Open Policy Agent, which go.mod pins as github.com/open-policy-agent/opa v1.12.3. That means rules are plain text files you can review and fork.

### Does KICS scan remote sources or only local files?

The dependency list includes hashicorp/go-getter, and the runtime image is built from checkmarx/git, which is consistent with fetching remote sources. The README does not spell out the remote-source workflow, so check the CLI help before relying on it.

### Is Checkmarx KICS free to use?

The repository is licensed Apache-2.0, which permits commercial use, modification and redistribution as long as the licence and notices are preserved. That covers the KICS repository itself; it says nothing about pricing for other Checkmarx products.

## Sources

- [Checkmarx/kics on GitHub](https://github.com/Checkmarx/kics)
- [License: Apache-2.0](https://github.com/Checkmarx/kics/blob/master/LICENSE)
- [Project website](https://kics.io)
- [README](https://github.com/Checkmarx/kics/blob/master/README.md)
- [Releases](https://github.com/Checkmarx/kics/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/checkmarx-kics
