Deployment guide

KICS

Overview

KICS (Keeping Infrastructure as Code Secure) is the open-source static-analysis scanner from Checkmarx. It finds security misconfigurations and compliance issues in Infrastructure as Code before the code is applied to a cloud account. KICS parses Terraform, CloudFormation, Kubernetes manifests, Ansible, Dockerfile and Docker Compose, Helm charts, ARM and Bicep, OpenAPI, gRPC, Pulumi and Crossplane, and evaluates each against an embedded query library that covers the security guidance of the major cloud and platform providers.

Every finding names the query, the platform, the file, the line, a severity (CRITICAL, HIGH, MEDIUM, LOW, INFO) and the CWE it maps to. Results can be written as JSON or SARIF for a code review, a dashboard or a pipeline gate. The query library ships with the scanner and is evaluated locally, so scanning needs no outbound internet at all. This VM can sit in a locked-down subnet with no egress and still scan.

This SecureAnyCloud image is a ready-to-run IaC security scanner host, not just the binary. The pinned scanner and its pinned query library are both verified against their published checksums at build time.

What you get:

  • KICS 2.1.20 (/usr/local/bin/kics), installed from the official release tarball and verified against the upstream SHA256 checksum
  • The full pinned query library (1811 queries) under /opt/kics/assets/queries, from the same release and checksum-verified, so scanning is fully offline
  • kics-scan, a wrapper that supplies the query paths, so kics-scan -p <dir> works with no flags to remember
  • kics-scan-run and kics-scan.timer, a daily scan of a directory you choose that writes JSON and SARIF reports with latest.* symlinks for CI pickup
  • Read-only self-test fixtures under /usr/share/kics/fixtures (an insecure Terraform sample and a locked-down clean sample), so you can prove detection works on your own VM
  • An appliance configuration at /etc/kics/scan.conf
  • 24/7 SecureAnyCloud support

This is a command-line product: no web UI, no listening service, no admin account and no password. SSH on port 22 is the only open port, and the SSH key you choose at launch is the only way in.

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting size.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network. No inbound application ports are needed, and scanning needs no outbound internet.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for KICS by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22).

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:kics-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name kics \
  --image sac1647283583153:kics-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

Step 3 - Connect to your VM

Connect over SSH as azureuser.

ssh azureuser@<vm-public-ip>

There is no password and no console to log in to, because this product has no credentials at all. /etc/kics/credentials on the VM is an informational note that says exactly that and points to the paths below.

Step 4 - Confirm KICS is installed

Check the installed version.

kics version
Keeping Infrastructure as Code Secure 2.1.20

The query library that ships with the image is pinned to the same release and installed read-only. Count its queries.

find /opt/kics/assets/queries -name metadata.json | wc -l
1811

Step 5 - Scan an insecure Terraform sample

The image ships a deliberately insecure Terraform fixture: a security group that opens every TCP port to 0.0.0.0/0. Scan it with the kics-scan wrapper, which supplies the pinned query paths for you. Results are written to the -o directory.

kics-scan -p /usr/share/kics/fixtures/insecure -o /tmp/kics-insecure --report-formats json,sarif; echo "exit: $?"

KICS prints a results summary and a per-query breakdown. This is the real output from this image: 66 HIGH findings, dominated by the wide-open ingress rule.

--- Results Summary --- CRITICAL: 0 HIGH: 66 MEDIUM: 3 LOW: 1 INFO: 3 TOTAL: 73 --- Queries Summary --- Platform Query Name Severity CWE Results Terraform Remote Desktop Port Open To Internet HIGH 668 1 Terraform Sensitive Port Is Exposed To Entire Network HIGH 200 63 Terraform Unknown Port Exposed To Internet HIGH 200 1 Terraform Unrestricted Security Group Ingress HIGH 668 1 Terraform HTTP Port Open To Internet MEDIUM 319 1 ... Results saved to file /tmp/kics-insecure/results.json

KICS exits with a non-zero status when it finds results, and the exit status reflects the highest severity found. This is what makes it usable as a pipeline gate.

Step 6 - Confirm a locked-down sample passes

The clean fixture is a security group restricted to a single port and a private CIDR. Scan it. It must report zero HIGH or CRITICAL findings.

kics-scan -p /usr/share/kics/fixtures/clean -o /tmp/kics-clean --report-formats json; echo "exit: $?"
--- Results Summary --- CRITICAL: 0 HIGH: 0 MEDIUM: 0 LOW: 2 INFO: 2 TOTAL: 4

The well-configured security group passes with no HIGH or CRITICAL misconfigurations. The remaining LOW and INFO notes (for example "Resource Not Using Tags") are informational hygiene, not security exposures.

Step 7 - Scan your own Infrastructure as Code

Put your IaC checkouts under /srv/iac (the default scan target), or point the scanner at wherever they already live. KICS auto-detects the platform (Terraform, Kubernetes, CloudFormation, Ansible, Dockerfile, Helm and more).

kics-scan -p /path/to/your/terraform -o /tmp/kics-report --report-formats json,sarif

You can also scan multiple paths and exclude directories. Run kics scan --help for the full flag set. The wrapper passes every flag through to kics scan.

Step 8 - Scheduled scans and machine-readable reports

kics-scan-run is the scheduled entry point. It reads /etc/kics/scan.conf, scans SCAN_TARGET, and writes both a JSON and a SARIF report with latest.* symlinks. Run it once by hand against the insecure fixture to see the reports appear.

sudo kics-scan-run /usr/share/kics/fixtures/insecure ls -l /var/lib/kics/reports/latest.json /var/lib/kics/reports/latest.sarif
[kics-scan-run] scanning /usr/share/kics/fixtures/insecure for IaC security misconfigurations [kics-scan-run] results found (KICS exit 50) - see /var/lib/kics/reports/kics-scan-20260719T201454Z.json [kics-scan-run] reports: ... (latest.json / latest.sarif updated) lrwxrwxrwx 1 root root ... latest.json -> .../kics-scan-20260719T201454Z.json lrwxrwxrwx 1 root root ... latest.sarif -> .../kics-scan-20260719T201454Z.sarif

GitHub code scanning, Azure DevOps and most IDEs consume SARIF directly, so you can upload latest.sarif as-is.

The scan timer and the first-boot provisioning unit are both enabled out of the box. Confirm it.

systemctl is-enabled kics-scan.timer kics-firstboot.service
enabled enabled

Step 9 - Reading the results (severity counts)

The JSON report carries a severity_counters object and a total_counter, so a pipeline can gate on severity without parsing the whole document.

jq -r '.severity_counters | "CRITICAL=\(.CRITICAL) HIGH=\(.HIGH) MEDIUM=\(.MEDIUM) LOW=\(.LOW) INFO=\(.INFO)"' /var/lib/kics/reports/latest.json
CRITICAL=0 HIGH=66 MEDIUM=3 LOW=1 INFO=3

A common CI gate fails the build if any HIGH or CRITICAL result is present.

HC=$(jq '(.severity_counters.CRITICAL // 0) + (.severity_counters.HIGH // 0)' /var/lib/kics/reports/latest.json) [ "$HC" -eq 0 ] || { echo "KICS found $HC HIGH/CRITICAL misconfiguration(s)"; exit 1; }

Configuration

The scheduled scan reads /etc/kics/scan.conf. Print the active settings.

grep -v '^#' /etc/kics/scan.conf | grep .
SCAN_TARGET="/srv/iac" REPORT_DIR="/var/lib/kics/reports" QUERIES_PATH="/opt/kics/assets/queries" LIBRARIES_PATH="/opt/kics/assets/libraries" REPORT_RETENTION_DAYS=30
  • SCAN_TARGET: the directory the daily scan walks for IaC. Point it at your checkouts.
  • QUERIES_PATH and LIBRARIES_PATH: the pinned, shipped query library and Rego libraries. Point QUERIES_PATH at your own directory of KICS queries to use a custom set.
  • REPORT_DIR and REPORT_RETENTION_DAYS: where reports are written and how many days of dated reports are kept.

After editing the file, restart the timer.

sudo systemctl restart kics-scan.timer

Custom queries and platforms

KICS ships the full query library in the image, so most users need no configuration. To restrict a scan to particular platforms or to add your own queries, pass the flags straight through the wrapper.

# Scan only Terraform and Kubernetes kics-scan -p /srv/iac --type Terraform,Kubernetes -o /tmp/kics-report
# Use your own directory of KICS queries kics-scan -p /srv/iac -q /etc/kics/my-queries -o /tmp/kics-report
# Fail only on HIGH or above kics-scan -p /srv/iac --fail-on high -o /tmp/kics-report

Run kics scan --help for the complete set of flags.

Maintenance

  • Scans: kics-scan.timer runs a scan daily. Run one on demand with sudo kics-scan-run, and inspect history with journalctl -u kics-scan.service.
  • Reports: /var/lib/kics/reports/latest.json and latest.sarif always point at the most recent scan. Dated reports are pruned after REPORT_RETENTION_DAYS.
  • Upgrades: download a newer release from the KICS releases, verify it against the published checksums.txt, and replace /usr/local/bin/kics and the query library under /opt/kics/assets.
  • Security patches: unattended-upgrades stays enabled, so the OS continues to receive security updates automatically.
  • Air-gapped use: scanning requires no egress. The query library is local, so this VM scans fully offline.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Deploy on Azure

Launch KICS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure