Is AI-Generated Terraform Secure? We Scanned It (2026)

August 29, 2026 · 5 min read
Quick answerNo — not by default. When you ask an AI assistant for a Terraform resource without mentioning security, it writes the minimal block from the provider documentation, and those blocks inherit insecure provider defaults. Scanning six common resources written this way produced 40 findings, 10 of them critical or high severity: unencrypted databases, storage without public-access blocks, and security groups open to 0.0.0.0/0 on port 22. The model is not doing anything wrong — a minimal aws_s3_bucket block is valid, idiomatic Terraform. It is just not safe. The fix is to give the assistant your security rules while it generates, rather than reviewing the output afterwards.

What exactly did we test?

We took the six resources people ask for most often and wrote each one the way an assistant writes it when the prompt says nothing about security — the minimal block, close to the first example in the provider documentation. Then we scanned each with Checkov, the same open-source engine Sovereign Observer runs.

This is deliberately not a strawman. Nobody wrote acl = "public-read" to make a point. These are the blocks you get from "add an S3 bucket for user uploads".

ResourceFindingsCriticalHigh
azurerm_storage_account1132
aws_db_instance1001
aws_s3_bucket701
aws_instance501
google_storage_bucket410
aws_security_group310

40 findings across 6 resources. 10 critical or high. An average of 6.7 findings per resource, before anyone has written a second line.

Why does a three-line resource produce seven findings?

Because Terraform providers optimise their defaults for it works, not for it is safe. A bucket that refuses public access, encrypts with a customer-managed key and versions every object is more secure and more likely to break someone’s first tutorial. So the default is the permissive one.

Take the S3 bucket. Three lines:

resource "aws_s3_bucket" "uploads" {
  bucket = "user-uploads"
}

That is valid, idiomatic Terraform. It also has no public access block, no versioning, no server-side encryption configuration, no access logging and no lifecycle policy. Every one of those is a separate resource in the AWS provider, and none of them exist unless you write them.

The model is not hallucinating. It is reproducing the documentation faithfully. The security gap is in the ecosystem, and the assistant inherits it.

Which failures actually matter?

Most of the 40 are hygiene — lifecycle policies, event notifications, tags on snapshots. Three patterns are worth stopping a merge for:

  • Open ingress. The default security group example allows 0.0.0.0/0 on port 22. That is one finding, and it is the one that turns into an incident. Public exposure is consistently the most exploited misconfiguration class.
  • Unencrypted data at rest. aws_db_instance has storage_encrypted off by default, and you cannot enable it on a running instance — you restore from a snapshot into a new encrypted one. Cheap to fix while it is text in an editor; a migration once it holds production data.
  • Missing deletion protection. Not a breach, but the finding that costs the most when it fires.

Azure is the worst of the three clouds on defaults: a minimal azurerm_storage_account produced 3 critical and 2 high findings, largely because public network access and shared key authorisation are both enabled unless you turn them off.

Why does asking the AI to "make it secure" not solve this?

It helps, and it is unreliable. Ask for "a secure S3 bucket" and you will usually get a public access block and encryption. You will not consistently get your requirements — the regions you are allowed to deploy into, the retention your auditor expects, the tags your finance team bills on. The model does not know those, so it invents plausible ones.

It also depends on the developer remembering to ask, every time, forever. Any control that requires people to care is a control that decays.

What actually works: give the rules to the generator

The useful shift is moving the check from after generation to during it. Instead of the assistant writing Terraform and then a scanner telling it what is wrong, the assistant asks what the rules are before it writes anything.

That is what the Model Context Protocol makes possible. An MCP server runs alongside your assistant in Claude Code, Cursor, VS Code or Windsurf, and the assistant calls it while it works:

You:       "add an RDS instance for the orders service"
Assistant: → asks what the policy requires
           ← storage_encrypted = true
             backup_retention_period ≥ 365
             region ∈ eu-west-1, eu-central-1
           [writes Terraform satisfying all three]
           → scans its own output → clean

The violation is never written, so there is nothing to review, argue about or fix. That is a different economic proposition from catching it in a pull request three days later.

How do I set this up?

Sovereign Observer ships a free, open-source MCP server. It runs entirely on your machine — no account, no API key, and your Terraform is never uploaded.

claude mcp add sovereign -- uvx sovereign-observer

For Cursor, VS Code and Windsurf configurations see the package README. Once installed, the assistant scans what it writes without being asked, because the server tells it to.

If you also want the same rules enforced on pull requests and against your live cloud accounts, that is what Sovereign Observer does — one rule set in the editor, in CI, and in production.

Frequently asked questions

Is AI-generated Terraform insecure?

By default, usually yes. Scanning six common resources written the way an assistant writes them without a security prompt produced 40 findings, 10 critical or high. The cause is insecure Terraform provider defaults rather than model error — a minimal resource block is valid, idiomatic code that simply omits every optional security setting.

Which cloud has the worst Terraform defaults?

In this test, Azure. A minimal azurerm_storage_account produced 11 findings including 3 critical, because public network access and shared key authorisation are enabled unless explicitly disabled. AWS RDS was next with 10 findings, mainly unencrypted storage and missing backup configuration.

Can I just ask the AI to write secure Terraform?

It improves the output but is not reliable. You will generally get encryption and public-access blocks, but not your organisation-specific requirements — approved regions, retention periods, required tags — because the model does not know them. It also depends on the developer remembering to ask every single time.

What is an MCP server for Terraform security?

A Model Context Protocol server that runs locally alongside an AI coding assistant and exposes security tools to it. The assistant can ask what your policy requires before generating a resource, then scan its own output before showing it to you, so the misconfiguration is never written rather than caught later.

Does the scanner send my Terraform anywhere?

The Sovereign Observer MCP server runs the scan in-process on your own machine and makes no network call in its default path — it works with networking disabled. Connecting an organisation token fetches your company rules, but that is a download of rules, never an upload of code.

See your cloud the way an attacker does.

Connect AWS, Azure or GCP with a read-only role you create yourself and get ranked attack paths in minutes. No sales call, and no keys stored on our side.