Safeguard
Security Guides•

Reviewing security group rules in IaC pull requests

What to check when a Terraform or CloudFormation change touches an AWS security group: open CIDRs, ports, references to other groups and default egress.

Safeguard Security Team
3 min read

When a pull request changes an AWS security group, check four things: who the source is, which ports are opened, whether a security group reference could replace a CIDR range, and whether outbound access has been narrowed. A source of 0.0.0.0/0 is fine on a public load balancer port 443 and rarely anywhere else.

Know the model first

From AWS documentation: security groups hold allow rules only, with no deny rules. A new group has no inbound rules, so no inbound traffic is allowed until you add some. It does have one outbound rule allowing all traffic, which you can remove. When several groups attach to a resource, their rules are aggregated.

That last point matters in review. A harmless looking group can be undone by another group attached to the same instance.

The review checklist

1. Source. What can reach this? A single address uses /32. 0.0.0.0/0 means the whole IPv4 internet, and ::/0 means all of IPv6. Both need a reason in the pull request.

2. Port range. Is it a single port, or a range like 0 to 65535? Management ports such as SSH and remote desktop open to the internet are the classic finding. Prefer a bastion alternative, a session manager or a private network path.

3. Reference instead of CIDR. AWS shows the standard three tier pattern. The load balancer accepts web traffic from 0.0.0.0/0. The web servers accept traffic only from the load balancer's security group. The database accepts traffic only from the web servers' group. If a pull request opens a database to a CIDR range, ask whether a group reference would do.

4. Egress. Is the default allow-all outbound left in place? For sensitive workloads, narrowing outbound limits what an attacker can reach after a compromise. If you remove it, confirm the workload still reaches updates, DNS and dependencies.

5. Description. Rules can carry a description up to 255 characters. Require one that says why the rule exists.

Infrastructure as code traps

  • A rule defined inline in the group and again as a separate rule resource can fight each other. CloudFormation's drift documentation notes that attachment style resources for ingress and egress can confuse results across stacks.
  • A variable that defaults to 0.0.0.0/0 and is overridden per environment. Check the default, not only the override.
  • Wildcards built from lists, where one bad entry opens everything.
  • Security groups reused by many services, so a change widens access for all of them.

Automate the easy part

Machine checks handle the obvious cases well: any ingress from an open CIDR on a port outside an allowlist, any rule without a description, any group with all ports open. Humans should spend their time on intent and architecture. Safeguard's policies and gates can enforce checks like these at pull request time, with exceptions recorded.

When an open rule is fine

A public web endpoint on 80 and 443, behind a load balancer, is a normal case. Record it as an approved pattern so reviewers need not rediscover the reasoning each time.

Quick check

Is 0.0.0.0/0 always wrong?

No. It is expected for public web ports on a load balancer. It is a red flag for management ports and databases.

Are security groups deny lists too?

No. AWS says you can specify allow rules but not deny rules. Anything not allowed is blocked.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.