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, sokics-scan -p <dir>works with no flags to rememberkics-scan-runandkics-scan.timer, a daily scan of a directory you choose that writes JSON and SARIF reports withlatest.*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 StandardStep 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 versionKeeping Infrastructure as Code Secure 2.1.20The 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 -l1811Step 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.jsonKICS 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: 4The 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,sarifYou 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.sarifGitHub 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.serviceenabled enabledStep 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.jsonCRITICAL=0 HIGH=66 MEDIUM=3 LOW=1 INFO=3A 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=30SCAN_TARGET: the directory the daily scan walks for IaC. Point it at your checkouts.QUERIES_PATHandLIBRARIES_PATH: the pinned, shipped query library and Rego libraries. PointQUERIES_PATHat your own directory of KICS queries to use a custom set.REPORT_DIRandREPORT_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.timerCustom 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-reportRun kics scan --help for the complete set of flags.
Maintenance
- Scans:
kics-scan.timerruns a scan daily. Run one on demand withsudo kics-scan-run, and inspect history withjournalctl -u kics-scan.service. - Reports:
/var/lib/kics/reports/latest.jsonandlatest.sarifalways point at the most recent scan. Dated reports are pruned afterREPORT_RETENTION_DAYS. - Upgrades: download a newer release from the KICS releases, verify it against the published
checksums.txt, and replace/usr/local/bin/kicsand 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
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 deployed. KICS parses Terraform, CloudFormation, Kubernetes manifests, Ansible, Dockerfile and Docker Compose, Helm, ARM and Bicep, OpenAPI, Pulumi, Crossplane and more. It reports where the declared infrastructure violates a security or compliance rule, such as a storage bucket with no encryption, a security group open to the world, or a container running as root.
This SecureAnyCloud image is ready to use. The pinned KICS binary and its full query library are installed with a zero-flag wrapper on the system path, so as soon as you connect over SSH you can run a real scan against more than 1800 built-in queries with no setup.
What you get:
- KICS 2.1.20 at
/usr/local/bin/kics, with its pinned Rego query library at/opt/kics/assets/queries - A wrapper at
/usr/local/bin/kics-scanthat supplies the query paths automatically - A daily systemd timer,
kics-scan.timer, that scans a configurable target directory (/srv/iacby default) and writes JSON and SARIF reports to/var/lib/kics/reports, with stablelatest.jsonandlatest.sarifsymlinks for CI pickup - Fully local scanning: because the query library is local, KICS needs no network egress and runs in a locked-down or air-gapped subnet
This is a headless command-line tool. There is no web interface, no daemon, no network port and no credential of any kind. The management surface is the kics CLI plus SSH with your own key, so there is nothing to rotate and nothing to leak. The instance security group opens port 22 only.
Findings are KICS working as designed. Review each one, fix the code, or exclude it.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for KICS. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, and either create or select a security group that opens port 22 from your management network. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialization takes a few seconds after the instance state becomes Running and the status checks pass. The KICS toolchain is ready by the time you can connect.
Launch the Instance from the AWS CLI
The command below launches an instance from the SecureAnyCloud KICS Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing. Replace <key-name> with your EC2 key pair name and <subnet-id> with your subnet ID. Replace <security-group-id> with a security group that opens port 22 from your management network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kics}]'When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name. You can find both in the EC2 console or with aws ec2 describe-instances.
Connect to Your Instance
Connect over SSH using your key pair and the login user for your operating system variant. For Ubuntu 24.04, the login user is ubuntu.
ssh -i /path/to/your-key.pem ubuntu@<public-ip>First boot writes a welcome note to /root/kics-instance.txt, recording the scanner version, the query count and the key paths. It contains no credentials. Read it with:
sudo cat /root/kics-instance.txtConfirm the Scanner and Its Query Library
Confirm the pinned KICS release and that the offline query library is present. kics version reports the release, and counting the query metadata files confirms the full library.
kics version find /opt/kics/assets/queries -name metadata.json | wc -lThe output shows the pinned release and the query count.
Keeping Infrastructure as Code Secure 2.1.20 1811The kics-scan wrapper on the system path supplies the pinned query and library paths for you, so kics-scan -p <directory> scans any path of infrastructure code with no flags.
Prove Real Detection with the Shipped Samples
Two read-only self-test fixtures ship on the image, so you can prove on first login that the scanner detects a real misconfiguration and passes clean code. The insecure fixture is a Terraform security group that opens every port to the whole internet. The clean fixture is a locked-down security group.
Scan the insecure sample first.
kics-scan -p /usr/share/kics/fixtures/insecure \
|| echo "kics exited non-zero by highest severity: the HIGH findings above are the expected result"KICS reports the failed queries with their severity and a count, and exits non-zero according to the highest severity found. Expect several HIGH findings, such as Sensitive Port Is Exposed To Entire Network and Unrestricted Security Group Ingress.
INF TOTAL: 73 --- Queries Summary --- Query Name Severity Results Sensitive Port Is Exposed To Entire Network HIGH 63 Unrestricted Security Group Ingress HIGH 1 Remote Desktop Port Open To Internet HIGH 1 HTTP Port Open To Internet MEDIUM 1Now scan the clean sample and count its HIGH or CRITICAL findings.
D=$(mktemp -d) kics-scan -p /usr/share/kics/fixtures/clean -o "$D" --report-formats json >/dev/null 2>&1 echo "HIGH/CRITICAL findings on the clean fixture: $(jq '((.severity_counters.CRITICAL // 0)+(.severity_counters.HIGH // 0))' "$D"/*.json)" rm -rf "$D"The locked-down configuration reports zero HIGH or CRITICAL findings. This is the signal a CI pipeline gates a merge on.
--- Queries Summary --- Query Name Severity Results IAM Access Analyzer Not Enabled LOW 1 Resource Not Using Tags INFO 1Scan Your Own Infrastructure Code
Point kics-scan at any directory or file of infrastructure code, and KICS auto-detects the platform (Terraform, CloudFormation, Kubernetes, Ansible, Dockerfile, Helm, ARM/Bicep and more). The general form is kics-scan -p /path/to/your/iac. Add -o /path/to/reports --report-formats json,sarif to write machine-readable reports.
The example below creates a small Terraform file and scans it end to end.
D=$(mktemp -d)
cat > "$D/main.tf" <<'EOF' resource "aws_s3_bucket" "example" { bucket = "sac-example-bucket" } EOF kics-scan -p "$D" -o "$D/reports" --report-formats json,sarif \
|| echo "kics exited non-zero by highest severity: review the findings above" rm -rf "$D"The exit code follows the KICS convention: 0 means no results, and a non-zero code identifies the highest severity found. The same command is therefore directly usable as a CI gate. The reports name each failed query, its severity, and the resource, file and line it applies to.
The Daily Scheduled Scan
A systemd timer runs a daily scan of the target directory and writes reports automatically. Put your infrastructure code in /srv/iac, or edit /etc/kics/scan.conf to point at wherever it lives, and the timer scans it each day.
# Confirm the timer is armed systemctl status kics-scan.timer --no-pager | head -3
# The daily scan covers /srv/iac, which ships empty. Drop a sample in and run it
# on demand (here we use the shipped insecure fixture as an example):
sudo cp /usr/share/kics/fixtures/insecure/main.tf /srv/iac/
sudo kics-scan-run \
|| echo "kics-scan-run exited non-zero by highest severity: the report was written"
# Read the severity counters from the most recent report
sudo jq '.severity_counters' /var/lib/kics/reports/latest.json
sudo rm -f /srv/iac/main.tfThe timer is active (waiting) and shows the next run time.
* kics-scan.timer - sac daily KICS IaC security scan Active: active (waiting) Trigger: Fri 2026-07-24 00:27:11 UTC; 22h left Triggers: * kics-scan.serviceTo change the scan target, query paths or report retention, edit /etc/kics/scan.conf and restart the timer.
sudo nano /etc/kics/scan.conf
sudo systemctl restart kics-scan.timerWire KICS into Your CI Pipeline
Because kics-scan exits non-zero when it finds results, you can gate a merge on a clean scan by running the same command in your pipeline. A typical pattern scans the repository and fails the job on any HIGH or CRITICAL finding, using the JSON report.
# Fail the build on any HIGH/CRITICAL finding kics-scan -p . -o ./kics-report --report-formats json
HC=$(jq '((.severity_counters.CRITICAL // 0)+(.severity_counters.HIGH // 0))' ./kics-report/*.json) if [ "$HC" -gt 0 ]; then echo "KICS found $HC HIGH/CRITICAL issue(s)"; exit 1; fiThe SARIF report (--report-formats sarif) uploads directly to code-scanning dashboards that accept SARIF, so KICS findings surface alongside the rest of your security signal.
Security and Maintenance
- KICS is installed as the SHA256-verified upstream release binary with its pinned query library.
- The operating system is installed from the Ubuntu archive and covered by standard unattended security updates.
- The scanner opens no network socket and runs no daemon, so its only remote surface is SSH with your own key.
- The query library is local, so scans need no outbound network access.
- Keep the instance patched with routine OS updates, and move to a newer SecureAnyCloud image when a newer KICS release is available.
Support
SecureAnyCloud provides 24/7 technical support by email and live chat for this image. We can help with running scans, interpreting findings, writing exclusions and custom queries, wiring KICS into CI, and keeping your infrastructure code compliant. Contact sales@secureanycloud.com with any question about deploying or operating this product.
Deploy on AWS
Launch KICS on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com