KICS on AWS User Guide
Overview
This image runs KICS (Keeping Infrastructure as Code Secure), the open source static analysis scanner from Checkmarx that finds security misconfigurations and compliance issues in infrastructure-as-code before it is ever deployed. It parses Terraform, CloudFormation, Kubernetes manifests, Ansible, Dockerfile and Docker Compose, Helm, ARM and Bicep, OpenAPI, Pulumi, Crossplane and more, and 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. The image is delivered ready to use: the pinned KICS binary and its full query library are installed with a zero-flag wrapper on the system path, so the moment you connect over SSH you can run a real scan against more than 1800 built-in queries with no setup.
This is a headless command-line tool. There is no web interface, no daemon, no network port and no credential of any kind. The scanner's entire management surface is the kics CLI plus SSH with your own key, so there is nothing to rotate and nothing to leak. KICS 2.1.20 is installed at /usr/local/bin/kics, its pinned Rego query library at /opt/kics/assets/queries, and a wrapper at /usr/local/bin/kics-scan supplies the query paths automatically. Because the entire query library is local, KICS needs no network egress to scan and runs happily in a locked-down or air-gapped subnet. The instance security group opens port 22 only.
A daily systemd timer, kics-scan.timer, scans a configurable target directory (/srv/iac by default) and writes machine-readable JSON and SARIF reports to /var/lib/kics/reports with a stable latest.json / latest.sarif symlink for CI pickup, so you can leave infrastructure code in one place and have it re-checked automatically. Findings are KICS working as designed: review each one, fix the code, or exclude it.
Prerequisites
Before you deploy this image you need:
- 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
Step 1: 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 cloudimg 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 initialisation 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.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg KICS Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <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 from the EC2 console or with aws ec2 describe-instances.
Step 3: Connect to Your Instance
Connect over SSH using your key pair and the login user for your operating system variant.
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i /path/to/your-key.pem ubuntu@<public-ip>
A welcome note is written to /root/kics-instance.txt at first boot recording the scanner version, the query count and the key paths. There are no credentials in it. Read it with:
sudo cat /root/kics-instance.txt
Step 4: Confirm the Scanner and Its Query Library
Confirm the pinned KICS release and that the offline query library loaded. kics version reports the release, and counting the query metadata files confirms the full library is present.
kics version
find /opt/kics/assets/queries -name metadata.json | wc -l
You should see the pinned release and a query count in the thousands:
Keeping Infrastructure as Code Secure 2.1.20
1811

The 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.
Step 5: Prove Real Detection with the Shipped Samples
Two read-only self-test fixtures ship on the image so you can prove the scanner detects a real misconfiguration and passes clean code on your first login. 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 by the highest severity found. You will see 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 1

Now 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, 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 1

Step 6: Scan 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, and adding -o /path/to/reports --report-formats json,sarif writes 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 = "cloudimg-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, so the same command is directly usable as a CI gate. The reports name each failed query, its severity, and the resource, file and line it applies to.
Step 7: The Daily Scheduled Scan
A systemd timer runs a daily scan of the target directory and writes reports automatically. Drop your infrastructure code into /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.tf
The timer is active (waiting) and shows the next run time:
* kics-scan.timer - cloudimg daily KICS IaC security scan
Active: active (waiting)
Trigger: Fri 2026-07-24 00:27:11 UTC; 22h left
Triggers: * kics-scan.service

To 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.timer
Step 8: Wire 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 SARIF or 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; fi
The 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 refresh to a newer cloudimg image when a newer KICS release is available.
Support
cloudimg 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 support@cloudimg.co.uk with any questions about deploying or operating this product.