AID-H-003.005: Infrastructure as Code (IaC) Security Scanning for AI Systems
Pillars: infra
Lifecycle: validation
Scope boundary
Owns security scanning and admission findings for Infrastructure-as-Code that provisions AI compute, storage, network, identity, pipelines, and serving environments before deployment.
AID-M-005.002: AID-H-003.005 scans a concrete IaC change for vulnerabilities and insecure resource definitions; AID-M-005.002 defines the signed policy-as-code baseline, posture criteria, and release gate used to judge configuration. The scanner evaluates the artifact, while the Model control owns the authoritative configuration-policy contract.
Implementation guidance
- AID-H-003.005-G001: Integrate IaC security scanners into the CI/CD pipeline to act as a merge blocker.
- AID-H-003.005-G002: Scan for hardcoded secrets within IaC and configuration files.
- AID-H-003.005-G003: Develop and enforce custom policies to prevent insecure network paths for AI workloads.
AID-H-003.005-G001
Production implementation: scan source and rendered plan as separate populations
name: IaC security gate
on: [pull_request]
permissions:
contents: read
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install policy-selected Terraform
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
with:
terraform_version: "${{ vars.VERIFIED_TERRAFORM_VERSION }}"
terraform_wrapper: false
- name: Render locked Terraform plan without deployment credentials
run: |
set -euo pipefail
mkdir -p reports
terraform -chdir=infrastructure init -lockfile=readonly -input=false
terraform -chdir=infrastructure plan -input=false -refresh=false -out=plan.tfplan
terraform -chdir=infrastructure show -json plan.tfplan > infrastructure/plan.json
test -s infrastructure/plan.json
- name: Scan IaC source population
id: source_scan
continue-on-error: true
uses: bridgecrewio/checkov-action@7b972723c44fb3d256283fac96fae5d7c1894bb7
with:
directory: infrastructure
soft_fail: false
output_format: cli,json
output_file_path: console,reports/checkov-source.json
- name: Scan rendered Terraform plan
id: plan_scan
continue-on-error: true
uses: bridgecrewio/checkov-action@7b972723c44fb3d256283fac96fae5d7c1894bb7
with:
file: infrastructure/plan.json
framework: terraform_plan
repo_root_for_plan_enrichment: infrastructure
soft_fail: false
output_format: cli,json
output_file_path: console,reports/checkov-plan.json
- name: Bind reports to exact inputs
id: bind_evidence
if: always()
run: |
set -euo pipefail
test -s reports/checkov-source.json
test -s reports/checkov-plan.json
test -s infrastructure/.terraform.lock.hcl
test -s infrastructure/plan.json
sha256sum infrastructure/.terraform.lock.hcl infrastructure/plan.json reports/checkov-source.json reports/checkov-plan.json > reports/iac-evidence.sha256
- name: Retain complete scan evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: "iac-security-evidence-${{ github.run_id }}-${{ github.run_attempt }}"
path: reports/
if-no-files-found: error
- name: Enforce both scan outcomes
if: always()
env:
SOURCE_SCAN_OUTCOME: "${{ steps.source_scan.outcome }}"
PLAN_SCAN_OUTCOME: "${{ steps.plan_scan.outcome }}"
EVIDENCE_OUTCOME: "${{ steps.bind_evidence.outcome }}"
run: |
set -euo pipefail
test "$SOURCE_SCAN_OUTCOME" = success
test "$PLAN_SCAN_OUTCOME" = success
test "$EVIDENCE_OUTCOME" = success
test -s reports/iac-evidence.sha256
Action and verification: Make this exact workflow check required by repository rules and repeat the source and plan scans before apply. Checkov's file input overrides directory, so separate steps are required to cover both populations. Keep the plan-rendering job free of production deployment credentials, pin Terraform through a protected policy variable, and run untrusted provider or module code only on an isolated ephemeral runner under the organization's network policy.
Retain the checked-out tree/commit, provider lock, module and policy digests, exact action commits, Terraform version, plan digest, both complete Checkov JSON reports, exceptions, runner image, workflow/run attempt, and the uploaded artifact digest/retention record. Exercise a clean change, a source-only finding, a generated-plan-only finding, render error, scanner error, stale exception, missing report, changed plan after scanning, and an IaC file outside the declared source population. Any missing population or non-success outcome blocks merge/apply; one report never substitutes for the other.
Before you begin
Apply AID-H-003.005-G001 only when infrastructure-as-code, rendered manifests, policies, or configuration deploy or change AI workloads and their data, model, network, or identity boundaries.
Keep the action safely bounded
Block merge or apply on uncovered files, scanner error, secret exposure, policy violation, stale exception, source-to-plan mismatch, or incomplete evidence retention.
AID-H-003.005-G002
Production implementation: scan current tree and full reachable history
name: IaC secret gate
on: [pull_request]
permissions:
contents: read
jobs:
secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Scan repository history
uses: trufflesecurity/trufflehog@17456f8c7d042d8c82c9a8ca9e937231f9f42e26 # v3.95.2
with:
path: ./
extra_args: --only-verified --fail
Action: Also scan generated plan JSON, rendered manifests, configuration bundles, and build artifacts before upload because they may contain resolved secrets absent from Git history. A verified secret blocks immediately; unverified high-entropy findings follow the signed review policy. Retain commit range, complete scanned-path manifest, excluded-path review, scanner/rule/database versions, raw findings, and post-remediation credential revocation evidence.
Before you begin
Apply AID-H-003.005-G002 only when infrastructure-as-code, rendered manifests, policies, or configuration deploy or change AI workloads and their data, model, network, or identity boundaries.
Keep the action safely bounded
block merge or apply on uncovered files, scanner error, secret exposure, policy violation, stale exception, or source-to-plan mismatch.
AID-H-003.005-G003
Before you begin
Apply AID-H-003.005-G003 only when infrastructure-as-code, rendered manifests, policies, or configuration deploy or change AI workloads and their data, model, network, or identity boundaries.
Production implementation: default-deny and port-bounded FQDN egress
This concrete policy applies only to an AI runtime whose signed egress manifest authorizes the OpenAI API and Hugging Face Hub. For another workload, the deployment renderer must replace the complete destination set from that workload's signature-verified manifest; sample, wildcard, or caller-supplied destinations are rejected.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: ai-workload-egress
namespace: ai-services
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/part-of: ai-runtime
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchName: api.openai.com
- matchName: huggingface.co
- toFQDNs:
- matchName: api.openai.com
- matchName: huggingface.co
toPorts:
- ports:
- port: "443"
protocol: TCP
Verification: A policy-as-code gate reconciles every rendered toFQDNs and DNS entry against the signed workload manifest and rejects missing or extra FQDNs, wildcards, unrestricted ports, IP-block escape routes, absent endpoint selectors, and unapproved DNS resolvers. After apply, read back the Cilium policy revision and endpoint enforcement status, then test both approved TLS destinations plus denied arbitrary DNS names, direct IPs, alternate ports, and IPv6 from every selected pod. Bind the signed result to the manifest digest, cluster, namespace, workload labels, policy bytes, Cilium version, DNS observations, and complete pod population.
Open-source tools
- Checkov
- Trivy
- KICS
- TruffleHog
- Gitleaks
- Open Policy Agent (OPA)
Commercial / hosted tools
- Snyk IaC
- Palo Alto Networks Prisma Cloud Application Security
- Wiz
- Tenable Cloud Security
Threat mappings
MITRE ATLAS
- AML.T0010 AI Supply Chain Compromise (IaC misconfigurations can compromise AI deployment infrastructure)
MAESTRO
- Infrastructure-as-Code (IaC) Manipulation (L4)
- Orchestration Attacks (L4) (IaC scanning detects Kubernetes misconfigurations)
- Lateral Movement (L4) (IaC scanning prevents insecure network paths enabling lateral movement)
- Supply Chain Attacks (Cross-Layer)
OWASP LLM Top 10 2026
- N/A
OWASP ML Top 10 2023
- N/A
OWASP Top 10 for Agentic Applications 2026
- N/A
NIST Adversarial Machine Learning 2025
- N/A
Cisco Integrated AI Security and Safety Framework
- AISubtech-14.1.2 Insufficient Access Controls
- AISubtech-9.1.3 Unauthorized or Unsolicited Network Access
- AITech-14.1 Unauthorized Access
- AITech-8.2 Data Exfiltration / Exposure
- AITech-8.3 Information Disclosure
Google Secure AI Framework 2.0 - Risks
- MDT: Model Deployment Tampering (IaC scanning prevents insecure deployment configurations)
Databricks AI Security Framework 3.0
- Platform 12.5: Poor security in the software development lifecycle
- Operations 11.1: Lack of MLOps - repeatable enforced standards (IaC scanning enforces infrastructure standards)