Infrastructure-as-Code (IaC) misconfigurations
Static policy checks on Terraform, CloudFormation, Kubernetes manifests, and Dockerfiles.
The Snitch CLI and GitHub Action ship with a deterministic IaC scanner that runs alongside the AI code review, the SCA dependency pass, and the DCA dead-code pass. It catches the cloud / orchestrator misconfigurations that turn an isolated app vuln into account-wide compromise.
It is on by default. No cloud credentials needed. No agent in production. Pure static analysis on the IaC files in your repo.
Frameworks supported
| Framework | Files parsed |
|---|---|
| Terraform | *.tf |
| CloudFormation | *.yaml / *.yml / *.json (auto-detected by AWSTemplateFormatVersion or Resources with Type: AWS::*) |
| Kubernetes | *.yaml / *.yml (auto-detected by apiVersion: + kind:, multi-doc files supported) |
| Dockerfile | Dockerfile, Dockerfile.<variant>, *.dockerfile |
Rules in v1
15 high-signal rules ship out of the box. Each is intentionally narrow to keep false positives low.
AWS / Terraform
| Rule | Severity | Catches |
|---|---|---|
IAC-AWS-S3-PUBLIC | Critical | S3 bucket with public-read ACL or disabled aws_s3_bucket_public_access_block |
IAC-AWS-IAM-WILDCARD | High | IAM policy with Action = "*" AND Resource = "*" AND Effect = "Allow" |
IAC-AWS-RDS-NO-ENCRYPTION | High | aws_db_instance with storage_encrypted = false or unset |
IAC-AWS-SG-OPEN-INGRESS | Critical | Security group with 0.0.0.0/0 ingress on SSH/RDP/MySQL/Postgres/Redis/Mongo/Elasticsearch ports |
IAC-AWS-SECRET-IN-TF | Critical | Hardcoded AWS / Stripe / Slack / private key in TF source |
CloudFormation
| Rule | Severity | Catches |
|---|---|---|
IAC-CFN-S3-PUBLIC | Critical | S3 bucket with AccessControl: PublicRead or permissive PublicAccessBlockConfiguration |
IAC-CFN-IAM-WILDCARD | High | AWS::IAM::Policy / AWS::IAM::Role with wildcard Action+Resource |
Kubernetes
| Rule | Severity | Catches |
|---|---|---|
IAC-K8S-RUN-AS-ROOT | High | Pod / Deployment without runAsNonRoot: true and no non-zero runAsUser |
IAC-K8S-PRIVILEGED | Critical | Container with privileged: true |
IAC-K8S-HOST-NETWORK | High | Pod with hostNetwork, hostPID, or hostIPC true |
IAC-K8S-NO-RESOURCE-LIMITS | Medium | Container missing both resources.limits.cpu and resources.limits.memory |
IAC-K8S-LATEST-TAG | Medium | Container image: ending in :latest or untagged |
Dockerfile
| Rule | Severity | Catches |
|---|---|---|
IAC-DOCKER-RUN-AS-ROOT | High | Final stage has no USER directive (defaults to root) |
IAC-DOCKER-CURL-PIPE-SH | High | RUN curl ... | sh or wget ... | sh patterns |
IAC-DOCKER-LATEST-BASE | Medium | FROM image:latest or untagged base image |
Output
In the sticky PR comment, a new 🏗️ Infrastructure misconfigurations section appears alongside the SCA / DCA / code-review sections. Findings are grouped by framework with a top-line table (count + worst severity per framework) and a per-framework collapsible containing every misconfig with its rule ID, resource type / name, file:line, and a one-line suggested fix.
In SARIF / GitHub Code Scanning, each finding becomes its own alert under a per-rule code-scanning rule (SNITCH-IAC-*). Stable fingerprints across runs so dismiss / triage state persists.
Disabling IaC
If you already run tfsec, checkov, kube-score, or another IaC scanner, you can opt out:
GitHub Action:
- uses: snitchplugin/snitch-github-action@v1
with:
snitch-license-key: ${{ secrets.SNITCH_LICENSE_KEY }}
include-iac: false
CLI:
snitch scan --skip-iac
SNITCH_SKIP_IAC=1 snitch scan
What it doesn't catch (and why)
- HCL interpolations (
var.foo,module.bar.baz) are passed through verbatim. The Terraform IAM-wildcard rule, for example, requires the literalAction = "*"token in the source — a wildcard injected via a variable won't trip it. We trade some recall for near-zero false positives. - Generated IaC (CDK output, Helm template render) is flagged at the rendered file, not the source. Best practice: scan the source (CDK code, Helm chart) at PR time, not the generated artifact.
- Multi-stage Dockerfile build stages running as root are not flagged — only the final stage matters for runtime. If your build stage runs as root and switches to non-root with
USERbefore the finalCMD, you're fine. - Custom CRDs in Kubernetes are skipped. We only check core resource types (Pod, Deployment, DaemonSet, StatefulSet, Job, CronJob).
- TF modules in private registries are not introspected. We only see the resource declarations in your repo's source tree.
Plugin (skill mode)
The Plugin variant doesn't scan filesystems, so the deterministic rule engine isn't available. Methodology category 71 instructs the AI to walk every *.tf / CFN template / K8s manifest / Dockerfile in the working set and apply the same patterns by inspection. Precision is lower than the deterministic CLI / Action path because the AI may miss subtle YAML structure or HCL interpolations; if you need real IaC scanning, run the CLI on the same repo.