Reviewing AI-Generated Infrastructure Code: What to Actually Look For



Crowds of fun-seekers exploring a city on foot, "

Arjan Franzen

31 July 2026

apbrpe.webp

Application code that is wrong usually breaks. Infrastructure code that is wrong works.

That is the whole problem in one sentence. Ask an AI agent for a bucket, a database and the permissions between them, and you get something back that passes plan, passes apply, and then runs perfectly happily. All green. And nothing in that tells you whether it is safe.

We review this kind of code regularly. Here is what we look at, in the order things go wrong.

What agents are genuinely good at

Worth being honest about what works, because it determines where not to spend your review time.

Agents are strong on form: correct syntax, sensible module structure, consistent naming, provider versions that line up, resources wired together properly. The boring parts — variables, outputs, tags — usually come out better than a human types them under deadline.

So that is not where your review time goes. It goes to the things a model has no visibility into: what already exists in your organisation, and what happens when somebody abuses this.

IAM first, always

This is where it almost always goes wrong, and it is rarely visible.

An agent wants your code to work. The fastest route to working code is broader permissions. So you get a role that can do slightly more than it needs, with a wildcard where a list belonged, and it works — which is precisely the point.

What we look for specifically:

  • Wildcards in actions or resources. s3:* or Resource: "*" is almost never what you meant. Ask which three actions are actually required.
  • Roles shared across services. Convenient during setup, and an immediately broad blast radius the moment one thing goes wrong.
  • Permissions inherited implicitly. If the new role inherits from something existing, the question is not what the diff says but what that parent can already do.
  • Long-lived credentials. If an access key is created instead of a role with short-lived tokens, that is a deliberate decision someone should make — not something an agent fills in for you.

Network rules that sit too wide

Same pattern, different layer. 0.0.0.0/0 is the fastest route to "it works", and it is almost never the answer.

Watch for security groups allowing inbound traffic on a management port, rules referencing a CIDR block where they should reference another security group, and resources that quietly acquire a public IP because that is how most examples online are written.

That last one is a recurring theme: a model is trained on public examples, and public examples are written to demonstrate something, not to run in production.

State, secrets and what ends up in them by accident

Three things we check as a matter of course, because they fail quietly:

  • Where does state live, and who can read it? Terraform state often holds sensitive values in plain text. A backend without encryption, or with permissive access, is a leak that never feels like one.
  • Are there secrets in variables with defaults? A default = "changeme" reaches production remarkably often.
  • Is anything being logged that should not be? Debug output on a resource that carries credentials is a classic.

What the diff does not show

This is the hardest part of the review, and the part that earns the most.

An agent sees what you give it. It does not see your existing landing zone, your naming conventions, the policy you introduced last year, or the fact that a near-identical resource already exists and could have been reused.

So ask of every change: does this already exist somewhere? Does it fit the structure we have? Does it cross a boundary we drew deliberately? You cannot put those questions to the model, because the answers were never in the context it was given.

A practical checklist

What we work through, in this order:

  1. Run plan and read that, not the code. The code describes intent; the plan describes what will actually happen. Pay attention to anything being replaced or destroyed.
  2. Grep for wildcards. Literally search for * in policies. Every hit needs a justification.
  3. Check network rules for 0.0.0.0/0 and for ports that have no business being public.
  4. Verify your state backend and its encryption.
  5. Ask what already exists. This is the step no tool does for you.
  6. Let automated scanners do the repeatable work. tfsec, checkov or your provider's policy tooling catch the known patterns, freeing your attention for context.

That last combination is the core of it: let the machine check what can be checked mechanically, and put your people on what only people know. As the volume of incoming code rises, that distinction becomes the difference between speed and risk.

In short

AI-generated infrastructure code is usually well written and regularly over-permissioned.

The mistakes are not in the syntax but in the permissions, the network boundaries, and everything the model could not know about your environment. They do not break anything — they work, which is exactly how they pass review.

So review in the order things go wrong: IAM first, then networking, then state and secrets, and then the question no model can answer — should this be here at all?

no image placeholder

Go Cloud Native, Go Big