Detecting Terraform Misconfigurations with Trivy: A Comparison Demo with Checkov

Tadashi Shigeoka ·  Sat, April 11, 2026

In a previous post, we created a Terraform vulnerability detection demo using Checkov (Checkov). This time, we scan the same Terraform code with Trivy and compare the results between the two tools.

Trivy is an open-source security scanner developed by Aqua Security. While widely known for container image scanning, it also supports IaC misconfiguration detection for Terraform, CloudFormation, Kubernetes manifests, and more.

Demo repository: codenote-net/trivy-terraform-demo

Key differences from Checkov

Even with identical Terraform code, Checkov and Trivy produce different results. Here is a summary of the key differences.

ItemCheckovTrivy
DeveloperPrisma Cloud (Palo Alto Networks)Aqua Security
Check ID formatCKV_AWS_XXX, CKV2_AWS_XXXAVD-AWS-XXXX
Severity levelsPASSED / FAILED onlyCRITICAL / HIGH / MEDIUM / LOW
Installpip install checkovbrew install trivy
Scan commandcheckov -d <dir>trivy config <dir>
ScopeIaC focusedContainer images, filesystems, IaC, SBOM, and more
Custom policiesPythonRego (OPA)
GitHub Actionsbridgecrewio/checkov-actionaquasecurity/trivy-action

The biggest difference is severity handling. Checkov classifies results as PASSED or FAILED. Trivy assigns CRITICAL / HIGH / MEDIUM / LOW severity to each finding, making it easier to prioritize remediation.

Repository structure

The structure mirrors the Checkov version: insecure/ contains vulnerable code and secure/ contains hardened code.

trivy-terraform-demo/
├── insecure/          # Intentionally vulnerable Terraform code
│   ├── provider.tf
│   ├── s3.tf
│   ├── sg.tf
│   ├── rds.tf
│   ├── iam.tf
│   └── cloudtrail.tf
├── secure/            # Hardened Terraform code
│   ├── provider.tf
│   ├── s3.tf
│   ├── sg.tf
│   ├── rds.tf
│   ├── iam.tf
│   └── cloudtrail.tf
└── .github/workflows/
    └── trivy.yml

The Terraform code is identical to checkov-terraform-demo. See PR #1 for implementation details.

Scanning with Trivy

Install Trivy via Homebrew:

brew install trivy

Run the scan against the insecure/ directory:

trivy config insecure/

To scan Terraform files only:

trivy config --misconfig-scanners terraform insecure/

To filter by severity:

trivy config --severity HIGH,CRITICAL insecure/

Unlike Checkov, which shows PASSED checks by default, Trivy only shows failures. To see all results including passed checks:

trivy config --include-non-failures insecure/

Scan results: 27 FAILURES

Trivy v0.69.3 detected 27 FAILURES. Compared to Checkov’s 37, that is 10 fewer detections.

Here is the breakdown by resource. Since Trivy assigns severity to each finding, the tables include a severity column.

S3: 11 findings (CRITICAL 1 / HIGH 6 / MEDIUM 1 / LOW 3)

AVD IDSeverityDescription
AVD-AWS-0086HIGHNot blocking public ACLs
AVD-AWS-0087HIGHNot blocking public policies
AVD-AWS-0089LOWAccess logging disabled
AVD-AWS-0090MEDIUMVersioning disabled
AVD-AWS-0091HIGHNot ignoring public ACLs
AVD-AWS-0092HIGHPublic ACL (public-read) is set
AVD-AWS-0093HIGHNot restricting public buckets
AVD-AWS-0094LOWNo corresponding public access block
AVD-AWS-0132HIGHNot encrypted with a customer managed key
AVD-AWS-0161CRITICALCloudTrail S3 bucket is publicly exposed
AVD-AWS-0163LOWCloudTrail S3 bucket logging disabled

Checkov flagged 8 S3 issues. Trivy checks each public access block setting individually (block_public_acls, block_public_policy, ignore_public_acls, restrict_public_buckets), resulting in more granular findings. It also flags the CloudTrail S3 bucket exposure as CRITICAL (AVD-AWS-0161).

Security Group: 6 findings (CRITICAL 1 / HIGH 2 / LOW 3)

AVD IDSeverityDescription
AVD-AWS-0104CRITICALUnrestricted egress to any IP address
AVD-AWS-0107HIGHUnrestricted ingress, all ports open to 0.0.0.0/0 (x2)
AVD-AWS-0124LOWRule missing description (x3)

Checkov also found 6 Security Group issues, but with different granularity. Checkov checks specific ports individually: SSH (CKV_AWS_24), RDP (CKV_AWS_25), HTTP (CKV_AWS_260). Trivy uses AVD-AWS-0107 as a catch-all for unrestricted ingress.

RDS: 6 findings (HIGH 2 / MEDIUM 3 / LOW 1)

AVD IDSeverityDescription
AVD-AWS-0077MEDIUMLow backup retention period
AVD-AWS-0080HIGHStorage encryption disabled
AVD-AWS-0133LOWPerformance Insights not enabled
AVD-AWS-0176MEDIUMIAM Database Authentication not enabled
AVD-AWS-0177MEDIUMDeletion protection not enabled
AVD-AWS-0180HIGHPublic access enabled

Checkov found 9 RDS issues. Trivy does not check for Enhanced Monitoring (CKV_AWS_118), CloudWatch Logs export (CKV_AWS_129), or Multi-AZ (CKV_AWS_157). On the other hand, Trivy adds checks for backup retention period (AVD-AWS-0077) and Performance Insights (AVD-AWS-0133).

CloudTrail: 4 findings (HIGH 2 / MEDIUM 1 / LOW 1)

AVD IDSeverityDescription
AVD-AWS-0014MEDIUMNot enabled across all regions
AVD-AWS-0015HIGHNot encrypted with a customer managed key
AVD-AWS-0016HIGHLog file validation disabled
AVD-AWS-0162LOWCloudWatch logging not configured

Checkov found 5 CloudTrail issues. The missing SNS topic (CKV_AWS_252) is not checked by Trivy.

IAM: 0 findings

This is the most significant difference. Checkov detected 9 FAILED checks for the IAM wildcard policy (Action: "*", Resource: "*"), including privilege escalation (CKV_AWS_286), credentials exposure (CKV_AWS_287), and data exfiltration (CKV_AWS_288). Trivy v0.69.3 detected none.

Checkov performs deep analysis of what a wildcard policy enables. Trivy does not cover this area. If IAM policy auditing is important, Trivy alone is insufficient. Consider pairing it with Checkov or IAM Access Analyzer.

Detection count comparison

ResourceCheckovTrivyDelta
S3811Trivy +3
Security Group66Same
RDS96Checkov +3
IAM90Checkov +9
CloudTrail54Checkov +1
Total3727Checkov +10

Scan results for the secure code

trivy config secure/

Result: 0 FAILURES. The same hardened code that passes all Checkov checks also passes all Trivy checks.

Integrating with GitHub Actions

The repository uses aquasecurity/trivy-action to run Trivy automatically on pushes and pull requests.

name: Trivy
 
on:
  push:
    branches: [main]
    paths:
      - "insecure/**"
      - "secure/**"
      - ".github/workflows/trivy.yml"
  pull_request:
    branches: [main]
    paths:
      - "insecure/**"
      - "secure/**"
      - ".github/workflows/trivy.yml"
 
permissions:
  contents: read
  pull-requests: write
 
jobs:
  scan-insecure:
    name: "Scan insecure/"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Run Trivy on insecure/
        uses: aquasecurity/trivy-action@0.35.0
        with:
          scan-type: config
          scan-ref: insecure/
          format: table
          exit-code: "0"
          severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
          hide-progress: true
 
  scan-secure:
    name: "Scan secure/"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Run Trivy on secure/
        uses: aquasecurity/trivy-action@0.35.0
        with:
          scan-type: config
          scan-ref: secure/
          format: table
          exit-code: "1"
          severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
          hide-progress: true

The CI control mechanism differs from Checkov. Checkov uses soft_fail: true/false, while Trivy uses exit-code. Setting exit-code: "0" allows CI to pass even with failures; "1" fails the build.

Takeaways

Checkov found 37 issues while Trivy found 27 against the same Terraform code. More detections does not necessarily mean one tool is better than the other.

Here is how to choose:

  • If IAM policy auditing matters, use Checkov: Trivy does not detect IAM wildcards
  • If you want prioritized remediation, use Trivy: Severity levels (CRITICAL/HIGH/MEDIUM/LOW) help triage
  • If you also scan container images, use Trivy: One tool covers both IaC and containers
  • For best coverage, use both: The check sets are complementary, not overlapping

Both tools require no terraform init and integrate easily into CI. Start with one, then add the other if you find coverage gaps.

That’s all from the Gemba, where we dual-wield Checkov and Trivy.