Infrastructure-as-code (IaC) is the definition of your cloud, Kubernetes, or container environment expressed as files. When those files are insecure β public S3 buckets, privileged containers, missing network policies β the infrastructure that gets deployed is insecure too. IaC security is the discipline of catching these misconfigurations before they become production incidents.
The case for scanning IaC
Industry data consistently shows that most cloud breaches are caused by misconfigurations, not zero-days. Public S3 buckets, security groups open to 0.0.0.0/0, Kubernetes pods running as root, unencrypted RDS instances β these are the volume issues. Each one is a single-line fix in the IaC, if caught before merge.
The tool landscape
- Checkov (Bridgecrew/Prisma) β multi-framework: Terraform, CloudFormation, Kubernetes, Dockerfile, ARM, Serverless, Helm. Good out-of-box rules, active maintenance
- tfsec β Terraform-focused, fast, clear output. Acquired by Aqua; maintained alongside Trivy
- Trivy β now a Swiss-army knife: container images, filesystems, IaC, secrets. One binary
- kube-score / kubesec β Kubernetes manifest static analysis. Complements admission controllers
- KICS β open-source IaC scanner from Checkmarx, broad framework support
- Semgrep β can write custom IaC rules in the same platform you use for code SAST
Recommendation for most teams: Checkov for broad coverage + Trivy for container images + custom Semgrep rules for your specific patterns.
Terraform β what to scan for
Categories of Terraform issues:
- Public exposure: S3 buckets with public ACL, security groups 0.0.0.0/0 on sensitive ports, RDS publicly_accessible
- Missing encryption: S3/EBS/RDS unencrypted, secrets in plaintext (Terraform state has them too)
- Logging/monitoring gaps: no CloudTrail, no VPC flow logs, no RDS logs
- IAM: wildcard permissions, overly broad trust policies, no MFA on privileged roles
- Backup/retention: no versioning, missing backup policies, short log retention
- Network: missing VPC endpoints (forcing traffic over internet), public subnets holding data services
Sample Checkov CI job
# .github/workflows/iac-scan.yml
name: IaC Scan
on:
pull_request:
paths: ['terraform/**', 'k8s/**', '**/Dockerfile']
jobs:
checkov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: terraform,kubernetes,dockerfile
output_format: sarif
output_file_path: checkov.sarif
soft_fail: false # fail the build on findings
skip_check: CKV_AWS_79 # specific known-accepted risks
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: checkov.sarif
Kubernetes β the deeper checklist
Kubernetes manifests have a specific set of security-sensitive fields:
- securityContext.runAsNonRoot β should be true
- securityContext.readOnlyRootFilesystem β should be true
- securityContext.allowPrivilegeEscalation β should be false
- securityContext.capabilities.drop: [“ALL”] β drop then selectively add
- Resource limits and requests β both CPU and memory, always
- No
hostNetwork: true, hostPID: true, hostIPC: true except where absolutely required
- ServiceAccount explicitly set (not default); RBAC scoped narrowly
- NetworkPolicy present (without one, pods can talk to every other pod)
- Pod Security Standards: at least
baseline, ideally restricted, on every namespace
- Ingress TLS configured; HTTP-only ingresses rejected
Sample Kubernetes manifest β secure defaults
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: prod
spec:
template:
spec:
serviceAccountName: api-sa
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
seccompProfile: {type: RuntimeDefault}
containers:
- name: api
image: registry.example.com/api:v1.2.3@sha256:abc...
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
ports: [{containerPort: 8080}]
Dockerfile β the scanning layer
Dockerfile-level patterns to catch:
π Intermediate Module Β· Basic Tier
Continue reading with Basic tier (βΉ499/month)
You've read 25% of this module. Unlock the remaining deep-dive, quiz, and every other Intermediate module.
99+ modulesAll levels up to this tier
20-question quizzesUnlimited retries with explanations
Completion certificatesShareable on LinkedIn
6 more sections locked below