Snyk IaC finds overly permissive IAM policies before they ever reach AWS by parsing Terraform HCL and CloudFormation YAML/JSON directly, converting each resource into a normalized internal model, and running that model through a policy engine built on Open Policy Agent (OPA) technology Snyk acquired with Fugue in August 2022. A single logical rule — "does this policy grant a wildcard action on a wildcard resource?" — can therefore fire identically whether the offending block is an aws_iam_policy resource in a .tf file or an AWS::IAM::Policy resource in a CloudFormation template. The engine doesn't need cloud credentials or a deployed stack; it reads source code, or a terraform plan JSON export, and reports the exact file and line where a Principal: "*" or Action: "*" statement lives, alongside a severity score and a suggested fix. This post walks through that mechanism step by step.
What actually happens when you run snyk iac test?
Running snyk iac test triggers a three-stage pipeline: parse, normalize, evaluate. First, Snyk's parsers read the raw IaC files — HCL for Terraform (.tf/.tf.json), YAML or JSON for CloudFormation, plus Kubernetes manifests, Helm charts, and Azure ARM/Bicep templates — and build an abstract syntax tree for each. Second, that tree is flattened into a resource-level intermediate representation: every aws_iam_policy, aws_iam_role_policy, or AWS::IAM::Policy block becomes a structured object with normalized fields for actions, resources, principals, and conditions, regardless of which IaC language it came from. Third, that normalized object is evaluated against Snyk's built-in rule set (and any custom Rego rules an org has added). The CLI then prints a result per finding: rule ID, severity (low/medium/high/critical), the file path and line number, a short description, and an "Introduced by" pointer showing exactly which resource block caused it — so a security engineer isn't left guessing which of forty modules produced the flagged policy.
How does Snyk compare a Terraform aws_iam_policy against a CloudFormation AWS::IAM::Policy?
It compares them by ignoring syntax and evaluating semantics against a shared attribute schema. Terraform's aws_iam_policy resource embeds its policy as a JSON string (often built with jsonencode() or the aws_iam_policy_document data source), while CloudFormation's AWS::IAM::Policy embeds the same policy shape as a native YAML or JSON PolicyDocument property. Snyk's normalization layer resolves both down to the same internal statement structure — Effect, Action, Resource, Principal, Condition — before any rule runs. That's what lets a single rule definition, such as "flag any statement where Action includes * and Resource includes *," apply identically across both formats instead of requiring Terraform-specific and CloudFormation-specific copies of every check. It's also why the same rule catalog covers Kubernetes RBAC bindings and Azure role assignments: the engine reasons about "who can do what to which resource," a pattern that recurs across every cloud IaC format.
What specific IAM misconfigurations does the rule engine catch?
The rule set targets a known list of high-risk IAM patterns rather than trying to infer intent. Documented categories include: wildcard actions ("Action": "*" or an overly broad action prefix like s3:*) paired with any resource scope; wildcard resources ("Resource": "*") paired with a sensitive action; wildcard principals in a trust policy ("Principal": "*" or "Principal": {"AWS": "*"}) that let any AWS account assume a role; missing Condition blocks on sensitive actions such as iam:PassRole or sts:AssumeRole, which is the classic setup for privilege-escalation chains; and policies attaching AWS-managed AdministratorAccess-equivalent permissions to a role that a workload doesn't need. Each finding maps back to a documented rule ID in Snyk's public rules catalog, and many map onward to CIS AWS Foundations Benchmark controls, so a single scan output can double as evidence for a compliance audit rather than just a developer to-do list.
Why can static scanning of a .tf file miss a permission that only shows up later?
Static scanning can miss permissions assembled dynamically because Terraform frequently builds the final policy value from variables, modules, for_each loops, and data sources that aren't resolved until terraform plan runs. A policy document that looks narrowly scoped in the raw HCL — say, a Resource field referencing a variable — might resolve to "*" once that variable's default or a module's output is substituted in. To close this gap, Snyk IaC also accepts terraform plan -json output as an input, scanning the fully resolved, post-interpolation configuration instead of just the source text. This is why Snyk recommends running snyk iac test against both the raw source (for fast, pre-merge feedback in a PR) and the plan output (for a pre-apply gate) — the two catch different failure modes, and relying on source-only scanning alone can let a dynamically-widened policy slip through.
How does Snyk decide which overly permissive policy to fix first?
Severity is assigned per rule based on the theoretical blast radius of the misconfiguration, then results can be layered with cloud context to reprioritize by actual exposure. A wildcard Action: "*" combined with Resource: "*" on a role that's also assumable by a wildcard principal is rated more severely than a narrowly wildcarded action on a resource ARN scoped to a single S3 bucket, because the former grants effectively unbounded account access. Snyk's platform layer (built on the same Cloud/Fugue-derived capability) can further enrich IaC findings with live cloud posture data — for example, flagging that a soon-to-be-deployed overly permissive role would attach to an instance that's internet-facing — so teams triage the handful of findings with real reachability instead of working through every wildcard match with equal urgency. Results also surface in pull requests through Snyk's GitHub, GitLab, Bitbucket, and Azure Repos integrations, with the option to block a merge when a new finding exceeds a configured severity threshold.
How Safeguard Helps
Understanding how a scanner like Snyk IaC reasons about Terraform and CloudFormation is useful context, but the underlying problem — permissive IAM sitting undetected in infrastructure code until it's exploited in production — is exactly what Safeguard is built to close across the rest of the software supply chain. Safeguard extends policy-as-code enforcement beyond the IaC layer into the CI/CD pipelines, build systems, and package registries that generate and consume those cloud credentials in the first place, so an overly permissive role isn't just flagged in a PR comment but tracked end-to-end from the commit that introduced it through the build job and artifact that inherit its permissions. For teams running IaC scanning as one control among many, Safeguard correlates those findings with SBOM data, provenance attestations, and CI identity usage to show whether a flagged IAM policy is actually being exercised by a live pipeline — turning a static-analysis finding into an actionable, evidence-backed remediation item rather than another line in a backlog.