Secure the PipelineIaCStep 18 of 31

Snyk IaC on the Same Terraform

difficulty intermediatehands-on 25 min hands-on

58% complete

prereqs · trivy-config-iac-scanning

concepts · scanner disagreement · severity models · set comparison · gate selection

Three tools have now run against the Range's Terraform: Checkov found 26, tfsec 14, trivy config 11. A fourth opinion on an artefact you already know this well is worth more than a first opinion on a new one — you can tell immediately whether a difference is a real gap or a naming difference.

Snyk also returned 11. That is the most misleading number in this track.

Verified against Snyk CLI 1.1306.3, org jaybilgaye, against the Range Terraform. Output copied from a real run.

Step 1 — Run it

bash
brew install snyk-cli
snyk auth                      # opens a browser; do not paste a token

git clone https://github.com/jaybilgaye/aiopsone-range
cd aiopsone-range

snyk iac test terraform/
text
Test Summary

  Organization: jaybilgaye
  Project name: jaybilgaye/aiopsone-range

✔ Files without issues: 1
✗ Files with issues: 1
  Total issues: 11 [ 0 critical, 4 high, 3 medium, 4 low ]

Zero criticals, on Terraform that declares a public S3 bucket, a security group open to the internet in both directions, and an IAM policy granting full administrative rights.

snyk auth opens a browser and stores the token for you. Do not paste an API token into a terminal you are recording, and do not export SNYK_TOKEN= in a shell whose history is saved.

Step 2 — The eleven

bash
snyk iac test terraform/ --json-file-output=snyk-iac.json
Severity ID Finding
high SNYK-CC-TF-95 S3 block public ACLs disabled
high SNYK-CC-TF-96 S3 block public policy disabled
high SNYK-CC-TF-97 S3 ignore public ACLs disabled
high SNYK-CC-TF-98 S3 restrict public bucket disabled
medium SNYK-CC-TF-1 Security Group allows open ingress
medium SNYK-CC-TF-1 Security Group allows open ingress
medium SNYK-CC-TF-119 IAM Policy grants full administrative rights
low SNYK-CC-TF-45 S3 server access logging disabled
low SNYK-CC-TF-124 S3 bucket versioning disabled
low SNYK-CC-TF-127 S3 bucket MFA delete disabled
low SNYK-CC-TF-73 Security Group allows open egress

Step 3 — Same total, different set

Match Snyk's eleven against Trivy's eleven by what they actually describe:

Finding Trivy Snyk
S3 block public ACLs AWS-0086 TF-95
S3 block public policy AWS-0087 TF-96
S3 ignore public ACLs AWS-0091 TF-97
S3 restrict public bucket AWS-0093 TF-98
S3 access logging AWS-0089 TF-45
S3 versioning AWS-0090 TF-124
SG open ingress ×2 AWS-0107 TF-1
SG open egress AWS-0104 TF-73
S3 encryption uses CMK AWS-0132 — absent —
SG rule missing description AWS-0124 — absent —
IAM full administrative rights — absent — TF-119
S3 MFA delete disabled — absent — TF-127

Nine shared. Two unique to each. Identical totals.

If you had run only the totals — 11 and 11 — you would have concluded the tools agree and that swapping one for the other is free. It is not: each is blind to two things the other sees, and one of those is full administrative IAM access.

This is why the Grype versus Trivy lesson insisted on comparing the set difference rather than the count. Here the counts are not merely uninformative, they are actively misleading. Two tools agreeing on a number is not two tools agreeing.

Terminal showing Snyk IaC and Trivy config each reporting 11 findings, with only nine in common and two unique to each

Step 4 — Now put all four side by side

bash
checkov -d terraform/ --compact
tfsec terraform/
trivy config terraform/
snyk iac test terraform/
Total Open ingress Open egress IAM full admin
Checkov 3.2 26 flagged flagged flagged
tfsec 1.28.14 14 CRITICAL CRITICAL HIGH
trivy config 0.72.0 11 HIGH CRITICAL not checked
Snyk IaC 1.1306.3 11 MEDIUM LOW MEDIUM

Read the egress column. The identical line of Terraform is CRITICAL to two tools and LOW to a third.

text
egress {
  from_port   = 0
  to_port     = 0
  protocol    = "-1"
  cidr_blocks = ["0.0.0.0/0"]     # everything, anywhere
}

Neither rating is indefensible. Unrestricted egress is how data leaves during an exfiltration and how a compromised host reaches a command-and-control server — that is the CRITICAL argument. It is also the default in most AWS accounts and in the majority of Terraform ever written, and a tool that pages you for the default configuration gets muted — that is the LOW argument.

The same split appears on ingress: CRITICAL, HIGH, MEDIUM across three tools.

Severity is a vendor's opinion, not a property of your infrastructure. Every one of these tools is calibrated against an imagined median user who is not you. A gate written as --severity CRITICAL is not a risk threshold; it is a bet that your scanner's product team shares your risk appetite.

Step 5 — What this does to your gate

Take one policy — "block the build on CRITICAL" — and apply it to all four:

  • tfsec: blocks on the security group. Two criticals.
  • trivy config: blocks on egress only. One critical.
  • Snyk IaC: blocks on nothing. Zero criticals in this entire file.
  • Checkov: does not use a critical band at all, so the policy does not translate.

Same infrastructure, same intent, four different outcomes — including one pipeline that is green on a public bucket, an open security group, and full-admin IAM.

Gate on findings you have decided matter, named explicitly, rather than on a severity band you do not control:

yaml
# .github/workflows/iac.yml
- name: Snyk IaC
  run: |
    snyk iac test terraform/ \
      --severity-threshold=medium \
      --report                       # sends results to the Snyk UI
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

--severity-threshold=medium is what it takes to catch the IAM policy here, and it is a decision you have to make per tool. A threshold copied between scanners does not mean the same thing on the other side.

Step 6 — Where Snyk IaC earns its place

Findings are the commodity; four tools produce them and largely overlap. Two things here are not commodity:

It found MFA delete. SNYK-CC-TF-127 appears in none of the other three. Bucket versioning without MFA delete means an attacker with the credentials can permanently remove objects — the exact control that separates "we have versioning" from "we have a recoverable bucket" in a ransomware scenario. That is a genuinely good check.

--report puts the result somewhere durable. The finding goes to the Snyk UI with a project, an owner and a history, rather than into CI output that expires with the log. That is the same argument the GitGuardian lesson made about incident state, and it is the same reason it matters for CPS 234: the auditable artefact is the record of assessment and remediation, not the scan.

The Snyk web UI after --report, showing the aiopsone-range target with two projects — terraform/broken.tf carrying 4 high, 3 medium and 4 low issues, terraform/main.tf clean — each stamped with an imported and tested time

This is what --report produces: terraform/broken.tf recorded with its 4 high, 3 medium, 4 low — the same eleven the CLI printed — and terraform/main.tf clean, each timestamped and owned. A terminal prints once and scrolls away; this persists, and that persistence is the product. When an assessor asks "when did you last scan this Terraform, and what was open", the answer is a page, not a grep through CI logs.

Against that: it is the only one of the four that needs an account, sends your configuration to a hosted service, and consumes a monthly test allowance on the free tier.

The recommendation from this track does not change: Checkov owns the IaC gate. It found 26 where the others found 11–14, it is actively maintained, and it flags the wildcard IAM policy that Trivy cannot see. Run Snyk alongside it if you want the MFA-delete class of check and a durable record — not instead of it.

What you learned

  • Snyk IaC and trivy config both reported 11 — and only 9 were the same. Two blind spots each. Equal totals are not agreement.
  • Snyk reported zero criticals on Terraform with a public bucket, an open security group and full-admin IAM.
  • Unrestricted egress: CRITICAL to tfsec and Trivy, LOW to Snyk. Ingress spans CRITICAL / HIGH / MEDIUM across three tools.
  • Snyk does flag the IAM wildcard (TF-119, medium) that Trivy has no check for — and is the only one of four to flag S3 MFA delete.
  • A --severity CRITICAL gate is a bet on a vendor's calibration. The same policy blocks twice, once, or never depending on which tool you picked.
  • Gate on named findings and a threshold you set per tool. Thresholds do not port between scanners.
  • Checkov still owns the gate. Snyk adds a check class and a durable record, not a replacement.