aquasecurity/trivy
IaC scanning
Active contributors: Owen Rumney, nikpivkin, knqyf263
Purpose
This page is the deep dive on the IaC engine itself: how parsers turn HCL/JSON/YAML into normalized provider models, how the Rego engine evaluates rules against those models, and how the result is turned into Misconfiguration findings. The user-facing feature is described in misconfiguration scanning; this page focuses on the internals.
The IaC engine in pkg/iac/ originated as the tfsec and defsec projects, which were folded into Trivy in 2022. It is the largest single subsystem in the repo (~91,000 Go lines).
Directory layout
pkg/iac/
├── adapters/ # per-format → provider-state adapters
├── detection/ # file-format detectors (HCL, JSON, YAML, ARM, Bicep, ...)
├── framework/ # rule namespaces and bundling
├── ignore/ # in-source ignore comments (`# trivy:ignore:AVD-...`)
├── providers/ # normalized cloud resource models
├── rego/ # Rego host: scanner, embed, custom-rule loader
├── rules/ # built-in (non-Rego) check helpers
├── scan/ # `Scan` entry point that aggregates parsers + Rego
├── scanners/ # per-format scanners (terraform, cloudformation, k8s, helm, ...)
├── severity/ # severity normalization
├── state/ # State / overall-result types
├── terraform/ # Terraform-specific shared types
└── types/ # shared types (Resource, Range, Metadata, ...)How a Terraform scan flows
sequenceDiagram
participant Misconf as pkg/misconf
participant TF as pkg/iac/scanners/terraform
participant Parser as terraform parser
participant Adapter as adapters/terraform
participant Providers as pkg/iac/providers/aws/...
participant Rego as pkg/iac/rego
participant Bundle as Trivy Checks bundle
Misconf->>TF: Scan(fs, options)
TF->>Parser: ParseFS(.)
Parser-->>TF: Module tree
TF->>Adapter: Adapt(modules)
Adapter->>Providers: build Provider state (S3, IAM, ...)
Adapter-->>TF: state.State
TF->>Rego: Scan(state)
Rego->>Bundle: load policies
Rego-->>TF: scan.Results
TF-->>Misconf: MisconfigurationsOther formats follow the same shape with their own parser and adapter; the Rego engine and provider state are shared.
Provider state
The state model in pkg/iac/state/state.go holds normalized resource lists per cloud. For example, state.AWS.S3.Buckets is a slice of aws.S3.Bucket regardless of whether the source was Terraform, CloudFormation, or Pulumi. Each resource carries its own Metadata (file path, line range, originating module) so findings can point back to source.
Adapters
Each (format, cloud) pair has an adapter under pkg/iac/adapters/<cloud>/<format>/ that maps parsed format-specific resources to the normalized provider shape. AWS has the most adapters because every Terraform AWS service has its own file. The adapter pattern is what made it tractable to share rules across Terraform, CloudFormation, and Helm.
Rego runtime
pkg/iac/rego/scanner.go wraps OPA's Go bindings. At init it:
- Loads the embedded built-in rules from
pkg/iac/rego/embed.go. - Optionally loads user-supplied rules from
--config-policy <dir>. - Optionally loads JSON data from
--config-data. - Scans the provider state, evaluating each rule against the relevant subset of resources.
Rule metadata (severity, AVD ID, title, description, remediation) lives next to the Rego file in YAML; Trivy reads both at load time.
File-format detection
pkg/iac/detection/ decides which scanner to dispatch for a given file. It uses heuristics — first line, file extension, top-level keys — rather than full parsing, because the dispatcher runs on every file the walker visits. The detection types are defined in pkg/iac/detection/detect.go (FileTypeTerraform, FileTypeCloudFormation, FileTypeKubernetes, FileTypeHelm, FileTypeDockerfile, FileTypeAnsible, FileTypeAzureARM, FileTypeBicep, FileTypeYAML, FileTypeJSON).
Helm and ARM peculiarities
- Helm scans both the chart sources and the rendered output. The Helm scanner renders templates with default values, then dispatches the rendered Kubernetes manifests through the Kubernetes scanner.
- Azure ARM/Bicep has a Bicep-to-ARM JSON pre-pass; the rest mirrors Terraform/CloudFormation.
Ignores
pkg/iac/ignore/ understands inline ignore comments (# trivy:ignore:AVD-AWS-0001, // trivy:ignore:AVD-DS-0001 expiry: 2025-01-01) and the --ignorefile (a global list of CVE/AVD IDs). Ignores carry an optional expiry date.
Performance
Two settings affect performance significantly:
--rego-include-deprecated-checks— adds a few hundred extra rules.--config-trace— enables Rego tracing (slows scans by 10x or more; for debugging only).
For very large Terraform repositories, consider --terraform-exclude-downloaded-modules to skip remote modules.
Integration points
- Misconfiguration scanning — feature-level overview.
- fanal — config-file analyzers detect IaC files.
- Database — distributes the Rego bundle.
Entry points for modification
- New parser —
pkg/iac/scanners/<format>/. Implement theScannerinterface (Scan(fs)). - New cloud service — extend
pkg/iac/state/state.gowith the new top-level field, add the resource shape underpkg/iac/providers/<cloud>/<service>/, then add adapters. - Tune Rego —
pkg/iac/rego/scanner.gois the primary surface. - Add a metadata field on findings —
pkg/iac/types/metadata.goand the renderers.
Key source files
| File | Purpose |
|---|---|
pkg/iac/scan/scanner.go |
High-level Scan orchestrator. |
pkg/iac/scanners/terraform/parser/parser.go |
HCL parser entry. |
pkg/iac/scanners/cloudformation/parser/ |
CloudFormation parser. |
pkg/iac/scanners/kubernetes/parser/ |
Kubernetes manifest parser. |
pkg/iac/scanners/helm/parser/ |
Helm chart parser. |
pkg/iac/scanners/dockerfile/parser/ |
Dockerfile parser. |
pkg/iac/scanners/ansible/parser/ |
Ansible parser. |
pkg/iac/scanners/azure/parser/ |
ARM/Bicep parser. |
pkg/iac/state/state.go |
Provider state aggregate. |
pkg/iac/rego/scanner.go |
Rego host. |
pkg/iac/rego/embed.go |
Embedded built-in rules. |
pkg/iac/ignore/ |
In-source ignore comments. |
pkg/iac/detection/detect.go |
File-format heuristics. |
See also
- Misconfiguration scanning — feature-level summary.
- Cloud scanning — provider-specific lens.
- Kubernetes scanning — extends Helm + Kubernetes scanners with live cluster support.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.