Reviewing Terraform Network and Security Group Changes With AI
A single 0.0.0.0/0 in a Terraform security group can expose a database to the internet. AI is a sharp second pair of eyes on network diffs, used carefully.
- #terraform
- #ai
- #networking
- #security
- #review
Network changes are the IaC equivalent of defusing a bomb in the dark. A security group rule is a few lines of HCL, the diff looks trivial, and the difference between “open this port to the app tier” and “open this port to the entire internet” is one CIDR block that reads almost identically at a glance. I’ve watched a cidr_blocks = ["0.0.0.0/0"] sail through review because it sat next to four innocent rules and everyone was tired.
Reading network rules for over-exposure is repetitive, pattern-heavy work — which is to say, exactly what AI does well as a fast junior reviewer. It can flag the open ingress, the missing egress restriction, the security group that references the wrong tier. What it can’t do is understand your network topology or your intent, and it absolutely never gets to apply a change or hold a cloud credential. It reviews; a human decides.
Why network review fails human eyes
Three reasons these slip through:
- CIDRs look alike.
10.0.1.0/24and0.0.0.0/0occupy the same visual space in a diff. - The rule’s blast radius isn’t local. A security group rule’s danger depends on what’s attached to that group — and that’s somewhere else in the config.
- Intent lives in someone’s head. “This should only be reachable from the load balancer” is never in the HCL.
AI helps directly with the first two and with the third only if you tell it the intent.
Give it the resolved rule, not the raw diff
Don’t paste a Git diff full of dynamic blocks and variable references. Render what the rule actually becomes. The cleanest source is the plan JSON, where variables are resolved:
terraform plan -out=tfplan
terraform show -json tfplan \
| jq '.resource_changes[]
| select(.type | test("security_group|network_acl"))
| {address, after: .change.after}' > net.json
Now net.json has the literal CIDR blocks, ports, and protocols after interpolation — the thing a model can reason about, instead of a var.allowed_cidrs it can’t see into.
Frame the prompt around exposure, with intent
The prompt that works states the intended posture and asks for deviations:
“Here are the security group and NACL changes from a Terraform plan, resolved to literal values. The intended posture: databases reachable only from the app tier, app tier reachable only from the load balancer, nothing reachable from
0.0.0.0/0except the load balancer on 443. Flag every rule that violates this. For each finding, name the resource, the offending rule, and why it’s a problem. Do not approve or reject the change — just report deviations.”
Stating the intended posture is what makes the review useful. Without it, the model can only flag obvious internet exposure; with it, the model can catch the app-tier rule that accidentally allows the database subnet, which no generic check would find.
Pro Tip: Ask the model to specifically list any rule where from_port and to_port span a wide range (like 0-65535). Wide port ranges paired with broad CIDRs are the highest-signal red flag and the easiest to overlook.
Catch the open ingress the obvious way too
AI is the smart layer; keep a dumb, deterministic layer underneath it. A grep-level check should fail CI on the unambiguous cases regardless of what the model says:
terraform show -json tfplan \
| jq -e '.resource_changes[]
| select(.type == "aws_security_group_rule")
| select(.change.after.type == "ingress")
| select(.change.after.cidr_blocks
| index("0.0.0.0/0"))
| select(.change.after.from_port != 443)' \
&& echo "BLOCKED: open ingress on non-443 port" && exit 1
The deterministic check handles “0.0.0.0/0 on a weird port — never.” The AI handles “this rule is technically fine but inconsistent with the tier model.” Layering them means the cheap, certain failures don’t depend on a language model being awake.
Wire it in without handing over credentials
The job that runs the AI review reads net.json and posts a comment. It has no backend, no apply, no cloud access:
# CI excerpt
network_review:
needs: [plan]
script:
- cat net.json | post-to-review-service # read-only, no creds
# This job cannot apply. It can only comment.
That separation is the entire safety model. The reviewing service could be fully compromised and still touch nothing — it sees resolved JSON and emits prose. The code review dashboard is where I collect these network findings alongside the human approval, so the AI’s exposure report and the sign-off live in one view. If a finding looks like an active misconfiguration rather than a proposed one, that’s a thread for incident response, not a PR comment.
Don’t forget egress and default-deny
Most network review obsesses over ingress and ignores egress, which is where data exfiltration risk lives. A model prompted only about “who can reach this” will happily wave through a security group that allows all outbound to 0.0.0.0/0. Make egress an explicit part of the posture:
“Also review egress rules. Our policy: workloads should only reach known destinations (the VPC, specific managed service prefixes, and 443 for outbound HTTPS). Flag any egress rule allowing all ports or all destinations, and note where a default-deny egress posture is missing.”
The model is good at spotting from_port = 0, to_port = 65535, cidr = 0.0.0.0/0 on egress once you tell it to care. A resolved view makes this concrete:
terraform show -json tfplan \
| jq '.resource_changes[]
| select(.change.after.type == "egress")
| {address, after: .change.after}'
Tightening egress is unglamorous and exactly the kind of thing a tired human reviewer skips — which is precisely why the tireless junior reviewer earns its keep here.
Reconcile the rule against what’s attached
A security group rule is only as dangerous as the resources attached to the group. “Open 5432 to 0.0.0.0/0” is catastrophic on a database group and merely sloppy on a group attached to nothing yet. The model can’t see attachments from the rule alone, so feed it the association:
terraform show -json tfplan \
| jq '.resource_changes[]
| select(.type | test("vpc_security_group|network_interface_sg"))
| {address, sg: .change.after}'
Hand that alongside the rules and ask the model to correlate: “which of these flagged rules apply to a security group attached to a database or other sensitive workload?” That correlation is what turns a generic finding into a prioritized one — and it’s still the human, looking at the real topology, who confirms the attachment is what the AI thinks it is before anything merges.
Hard rules for network review
- The model reports deviations from a stated posture. It never approves, and the pipeline ensures it can’t apply.
- Keep a deterministic check beneath the AI for the unambiguous cases. Don’t make “0.0.0.0/0 on port 22” depend on a model’s mood.
- A human reads every flagged rule against the real topology before merge. The AI doesn’t know your VPC; you do.
I keep the posture-aware review prompt in the prompt library, and the Terraform prompt pack ships a network-review prompt with the intent-statement scaffolding baked in so you’re not rewriting it per project.
Conclusion
Network and security group changes are where a one-character diff becomes a public database. Resolving rules to literal CIDRs, feeding them to an AI with your intended posture, and backing that with a dumb deterministic gate turns the riskiest part of a Terraform PR into a reviewed, two-layer checkpoint. The model catches what tired humans miss; humans and a credential-free pipeline keep it from ever acting. Defuse the bomb in the light, not the dark. More security-focused guides are in the Terraform category.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.