cd /news/ai-tools/iac-bench-2026-10-scoring-criteria · home › topics › ai-tools › article
[ARTICLE · art-164085] src=massdriver.cloud ↗ pub= topic=ai-tools verified=true sentiment=· neutral

iac-bench 2026-10 Scoring Criteria

Iac-bench released its 2026-10 scoring criteria reference, defining every rubric, expertise and judge criterion behind an iac-bench score, with weights and pass counts per item. The rubric carries a total weight of 86, with the two mandatory security-finding items H1 (public access block, weight 18, passed by 25/30 planning attempts) and H3 (encryption at rest, weight 14, passed by 30/30). The reference scopes criterion IDs to their fixture, so H1 in G001 and H1 in G003 are different criteria, and grades 14 judge doctrine sections at 0, 1 or 2.

by read19 min views2 publishedNov 4, 2026
iac-bench 2026-10 Scoring Criteria
Image: Massdriver (auto-discovered)

Upcoming Workshop: Citizen Developer Agentic Software Factory on AWS 11.4.26 @ 12PM PST

Register Here! Reference for every criterion behind an iac-bench score: each rubric item, expertise item and judged doctrine section, with weights and how many attempts passed.

Release 2026-10 · reference

This page defines every criterion behind an iac-bench score: each mechanical rubric item, each expertise item, and each section the judge grades. Other articles refer to criteria by ID, such as G002 H11 or the judge's Sensitive values, and this page is where those IDs are defined. For how the criteria combine into a score, see

Methodology. Criterion IDs are scoped to their fixture. H1 in G001 and H1 in G003 are different criteria. Always read an ID together with its fixture.

Prefix Layer What it covers
H Rubric (core) Security, data protection and operability that follow from the brief or universal practice
A Rubric (audience fit) Exposure: controls the audience needs.Restraint: settings it should not be handed.Budget: interface size.
B Rubric (baseline) Applies to every fixture: provider version constraints ( B1 ) and descriptions (B2 )
E Expertise Service-specific practices an expert adds without being asked; weight 1 each
Section name Judge One of 14 doctrine sections, graded 0, 1 or 2

Kind describes what an item treats as correct:

Kind Passes when
Hardcoded Every value the source can produce is secure: a literal, or an input confined to secure values. The resource exists unconditionally and stays secure in every plan the sweep produces. An input that can weaken the setting fails, even when its default is safe.
On by default The protection is on at defaults, with a real way to turn it off. Always on with no opt-out earns 0.75; off by default but reachable earns 0.5.
Offered The capability appears at defaults, or under at least one documented input.
Graded Credit for the best of several working mechanisms.
Budget Full credit at or under the soft input count, falling linearly to zero at the hard count.
Direct A direct check described in the item text.

Mandatory items are each fixture's most severe security failures. Failing one is reported as a security finding (⚠). It does not cap the score, but it marks the attempt unshippable.

The "Full credit" column counts attempts that earned the item's full credit, out of the attempts that passed the gate (a module that does not plan earns nothing). Partial credit counts as not full.

Mandatory (security findings): H1, H3. Total rubric weight: 86.

ID Weight Kind What passes Full credit (attempts that planned)
H1(mandatory) 18 hardcoded Privacy is a property, not a knob: a public access block exists with all four settings hardcoded true, its existence unconditional, and every planned instance stays fully enabled across the entire sweep. 25/30
H3(mandatory) 14 hardcoded Encryption at rest is a property, not a knob: configured unconditionally in the source (dedicated resource or inline), present in every reachable plan. Which algorithm is a design choice; whether to encrypt is not. 30/30
H6 6 offered Lifecycle cost management volunteered: transition and/or expiration rules appear at defaults or under some documented input. 22/30
H7 4 offered Noncurrent-version handling: expiration or transition for old object versions. (Multipart-upload cleanup is expertise item E2; the same evidence is never paid twice.) 22/30
H8 5 offered Versioning offered: enabled at defaults or under some input. 30/30
H9 4 offered Server access logging offered: the mechanism (direct toggle or inferred from a generalized setting) is a design choice and not scored. 11/30
A1 2 Direct Exposure: consumers can influence the bucket's name (directly, as a prefix, or through a concept such as purpose). Naming is the one input every app team obviously has. 30/30
A2 2 Direct Restraint: no encryption key is demanded. Default S3 encryption or an optional customer-managed key both pass; a required KMS key input fails here while still earning H3, so demanding a key costs partial credit. Disabling encryption is H3's failure, not… 30/30
A3 1 Direct Restraint: no input controls object ownership or ACLs. 27/30
A4 2 Direct Restraint: no CDN or static-website architecture: no distribution, origin access control, or website configuration at defaults or under any documented input, and no bucket policy granting the CloudFront service. Distribution was never part of the request. 30/30
A5 8 budget Interface budget: full credit at 8 or fewer inputs, falling linearly to zero at 16. This audience fills in "a couple of obvious inputs". A race to expose every setting in order to satisfy exposure checks is the failure this guards against: pass-through… 14/30
H12 2 graded Consumers can add their own tags through an optional input. Full credit when that input feeds the provider's default_tags, so every resource is tagged by one setting; half credit when it is applied resource by resource, which every new resource must… 5/30
H15 4 Direct Explicit provider configuration with a configurable region: the module declares its aws provider block and an input feeds its region (a default is fine). A standalone module that relies on the implicit provider leaves the region to whatever environment… 12/30
H13 4 Direct Access logging actually works: some bucket policy's document grants the logging service permission to deliver. Checked in the policy expression (resolved through locals), not plan JSON: ARN-interpolating policies are unknown at plan time. 0/30
H14 3 Direct force_destroy is accessible (per Destructive defaults): some documented input influences it, directly or inferred from a concept such as environment. Hardcoded either way, or absent entirely, leaves the consumer no way out. Influence is detected… 23/30
B1_provider_constraints 5 Direct required_providers declared with constraints that cannot admit a new major version (~>, an upper bound, or a pin): an unconstrained provider is broken, not a style choice. 11/30
B2_descriptions 2 Direct Every variable and output carries a description. 30/30
Expertise item What it detects Present
E1 ownership controls BucketOwnerEnforced ownership controls (ACLs disabled). 30/30
E2 multipart cleanup Aborts incomplete multipart uploads (storage garbage collection). 26/30
E4 tls enforcement Bucket policy denies non-TLS (aws:SecureTransport) access. 26/30
E5 regional domain output Outputs bucket_regional_domain_name for downstream wiring. 30/30
E6 intelligent tiering Uses or offers Intelligent-Tiering storage class awareness. 6/30
E7 name uniqueness Bucket names include a uniqueness mechanism (random suffix, account id) seen through locals, or delegate to bucket_prefix: S3's namespace is global. Kept out of the core rubric: forced suffixes have drawbacks and consumers may legitimately want exact names. 12/30
E9 consumer access policies Ships ready-to-attach access policies for the bucket's consumers (read-only and/or read-write), as managed IAM policies or as policy documents exposed through outputs. 7/30

Mandatory (security findings): H1, H2. Total rubric weight: 92.

ID Weight Kind What passes Full credit (attempts that planned)
H1(mandatory) 14 hardcoded No public IP: the instance is reachable only on the private network. ipv4_enabled is hardcoded false, and every planned instance keeps it false across the sweep. Network reachability is never a knob, whoever the audience is. 23/28
H2(mandatory) 10 hardcoded Encrypted connections are required on every planned instance. Every ssl_mode value the source can produce rejects unencrypted clients: a literal, or an input confined to such modes (a bool choosing between them, or a validation listing them), and no plan… 19/28
H3 6 on by default Deletion protection ships on with a real opt-out: either the native API-level flag or the provider-level guard. Hardcoded on in either form leaves no way to retire an instance. 27/28
H4 6 on by default Automated backups ship on with a real opt-out (full credit); always-on with no opt-out earns partial credit: DBAs running throwaway instances lose the choice, but nothing is blocked. Hardcoded off or absent fails. 10/28
H5 4 on by default Point-in-time recovery ships on with a real opt-out (full credit); always-on earns partial credit: retained transaction logs bill as backup storage, so test instances legitimately turn it off. Hardcoded off or absent fails. 9/28
H6 4 offered High availability is offered: a regional (failover) instance appears at defaults or under some documented input. 27/28
H7 4 Direct No raw credential input: no variable feeds an instance root password or a database user password. Generated secrets, write-only values from a secret store, or IAM authentication all pass; demanding the secret as a plain input fails (Sensitive values). 25/28
H8 2 Direct Consumers can add their own labels through an optional input that reaches the instance's user_labels. Cloud SQL instances keep labels inside settings and do not inherit the provider's default_labels, and nothing else this module creates carries labels, so… 27/28
H9 4 graded Explicit provider configuration with a configurable region. Full credit when an input feeds the google provider's region (a default is fine); half credit when an input feeds the instance's region while the provider configuration stays implicit. Neither… 18/28
H10 4 Direct No database password stored in state: no database user's password and no instance root password is set through an attribute OpenTofu records. IAM database authentication, or write-only passwords (password_wo, root_password_wo), pass; generated or supplied… 24/28
H11 4 graded Removing a database from the module's input does not drop its data by default. google_sql_database deletes the database when it leaves the configuration unless deletion_policy is ABANDON or the resource is protected with prevent_destroy. Full credit for a… 4/28
A1 2 Direct Exposure: machine tier (sizing) is a DBA decision. 28/28
A2 2 Direct Exposure: the PostgreSQL major version is a DBA decision. 27/28
A3 2 Direct Exposure: engine flags (database_flags) can be set per instance. 26/28
A4 2 Direct Exposure: the maintenance window (day and/or hour) is controllable. 27/28
A5 2 Direct Exposure: the backup schedule or retention (start time, retained backups, or transaction-log retention) is controllable. 27/28
A6 1 Direct Exposure: storage sizing (disk size or autoresize limit) is controllable. 28/28
A7 2 Direct Exposure: the VPC network the instance attaches to is an input (required or defaulted), directly or through a data-source lookup. The brief names one network per environment; hardcoding one bakes an environment into a reusable module. 28/28
A8 8 budget Interface budget: full credit at 25 or fewer inputs, falling linearly to zero at 35. A DBA team legitimately owns many controls (edition, zones, disks, databases, IAM users, backup placement); past 35 the interface reads as pass-through. A race to expose… 16/28
A9 2 Direct Restraint: no networking setup. The brief says the network team owns the VPCs and has already configured private services access, so the module creates no peering range or service networking connection, at defaults or under any input. Building networking… 28/28
B1_provider_constraints 5 Direct required_providers declared with constraints that cannot admit a new major version (~>, an upper bound, or a pin): an unconstrained provider is broken, not a style choice. 6/28
B2_descriptions 2 Direct Every variable and output carries a description. 28/28
Expertise item What it detects Present
E1 backups survive deletion Automated backups outlive the instance: retain_backups_on_delete or a final backup on deletion. Cloud SQL otherwise deletes them with it. 0/28
E2 customer managed key A customer-managed encryption key can be supplied (encryption_key_name). Settable only at creation; needed where policy requires the company to hold and be able to revoke its keys. 12/28
E3 iam database login IAM database authentication is enabled (the cloudsql.iam_authentication flag), so people and workloads log in with their Google identity and a short-lived token instead of a password. 27/28
E4 manages databases The DBAs can declare the instance's databases through an input. Managing databases is a core DBA responsibility. 25/28
E5 manages users The DBAs can declare the instance's database users (IAM or built-in) through an input. Managing users is a core DBA responsibility. 26/28
E6 iam login granted The IAM principals given database users are also granted roles/cloudsql.instanceUser. Without it the database user exists but IAM authentication refuses the login. 13/28
E7 workload identities Workload service accounts can be given database logins (CLOUD_IAM_SERVICE_ACCOUNT users), not only people. The applications on GKE and Compute Engine connect with their own Google identities. 25/28
E8 connection audit trail Connections and disconnections are logged (log_connections and log_disconnections), so every session is recorded under the identity that opened it for the security team's audit. 12/28
E9 query insights Query Insights is enabled, giving the DBAs per-query load, latency and plan history in the console without running their own tooling. 21/28

Mandatory (security findings): H1, H2. Total rubric weight: 72.

ID Weight Kind What passes Full credit (attempts that planned)
H1(mandatory) 10 hardcoded HTTPS only: plain-HTTP requests are redirected, hardcoded on every web app and deployment slot and present across the sweep. The provider default is off. 22/28
H2(mandatory) 8 hardcoded Basic-auth publishing is disabled on every web app and deployment slot: neither FTP nor Web Deploy accepts the shared publishing credentials. Both default to ON in the provider. 18/28
H3 6 Direct Transport stays strong: TLS for the site and the deployment (SCM) endpoint is 1.2 or newer, FTP is disabled or FTPS-only, and remote debugging is off, on every planned app and deployment slot, and none of these is fed by an input. 25/28
H4 4 hardcoded A managed identity is attached unconditionally, so the app can reach other Azure services without stored credentials. 26/28
H5 4 offered Health checks are offered: a health-check path is configured at defaults or under some documented input, so unhealthy instances are taken out of rotation. 28/28
H6 4 offered Observability is offered: diagnostic settings or Application Insights appear at defaults or under some documented input. 28/28
H7 3 offered Redundancy is offered: zone balancing on the service plan appears at defaults or under some documented input, including inputs the module requires together (zone balancing with enough instances). 24/28
H9 4 offered Rollouts are offered: a deployment slot (azurerm_linux_web_app_slot) is declared, at defaults or behind an input, so a release can be staged, warmed and swapped into production instead of replacing the running app in place. 27/28
H8 2 Direct Tagging support is table stakes: consumers can add their own tags to the web app through an optional input. 25/28
A1 2 Direct Exposure: the plan size (SKU) is an SRE capacity decision. 28/28
A2 2 Direct Exposure: instance count or autoscale bounds are controllable. 28/28
A3 2 Direct Exposure: the health-check path is set per service. 28/28
A4 2 Direct Exposure: which container image runs is set per service. 27/28
A5 2 Direct Exposure: application settings (environment) can be supplied. 28/28
A6 2 Direct Restraint: no input for App Service worker internals (32-bit worker, HTTP/2, load-balancing mode, in-app MySQL). The brief's audience explicitly doesn't want to hand-tune these. 25/28
A7 8 budget Interface budget: full credit at 20 or fewer inputs, falling linearly to zero at 30. An SRE team owns capacity, availability, health, rollout, and observability controls. A race to expose every setting in order to satisfy exposure checks is the failure… 9/28
B1_provider_constraints 5 Direct required_providers declared with constraints that cannot admit a new major version (~>, an upper bound, or a pin): an unconstrained provider is broken, not a style choice. 26/28
B2_descriptions 2 Direct Every variable and output carries a description. 28/28
Expertise item What it detects Present
E1 autoscale rules Capacity follows load: an autoscale setting scales the plan between bounds instead of a fixed instance count. 24/28
E2 container port The container's listening port reaches App Service (WEBSITES_PORT), so images that don't listen on port 80 receive traffic and pass health checks. 23/28
E3 metric alerts Metric alerts are defined (for example 5xx rate, response time or health-check status), so the SREs are paged on symptoms rather than discovering them in dashboards. 16/28
E4 registry pull identity Images are pulled from the container registry with the app's managed identity (container_registry_use_managed_identity), so no registry password is stored in app settings. 18/28
E5 key vault references Secrets reach the app as Key Vault references in app settings (@Microsoft.KeyVault(...)), resolved by the managed identity, so secret values never sit in app settings or state. 6/28

The judge, Claude Opus 5.5, grades 14 sections of the quality doctrine (docs/good-opentofu.md). Each grade is 0, 1 or 2, and each is the median of three independent readings. A section with nothing to apply to earns 2. The overall judge grade is the weighted mean, scaled to 0–100.

Section Weight Earns 2 Typical reasons for less
Sensitive values 3 Secrets marked sensitive ; references to secrets accepted instead of raw values; no secret hardcoded or given as a default Raw passwords or tokens as plain inputs; secret-bearing outputs not marked sensitive
Interface design 2 Inputs are the decisions that genuinely vary for this use case and audience, expressed as concepts; the module makes every decision the use case settles Pass-through variables (one per attribute); knobs the audience should not own; decisions the brief leaves open, hardcoded
Variables and validation 2 Realistic mistakes are caught with teaching messages; no condition rejects a valid value; no avoidable pair of inputs that can conflict 1: guards are deliberate but one is missing, too strict, or the module adds a conflicting pair.0: essentially no validation.
Scope 2 The resources a competent operator considers part of the job (access posture, encryption, cost and data hygiene), in proportion Missing hygiene or access pieces; architecture the brief never implied
Internal logic 1 Locals derive values from concept inputs and make the module easier to read Duplicated blocks; clever expression chains; dead locals
Inline vs separate resources 1 Separate resources where the provider supports both forms Inline blocks without justification; both styles for the same attributes
Outputs 1 The IDs, endpoints and names a consumer needs Missing essentials; every attribute dumped
Iteration ( for_each vscount ) 1 for_each for multiplicity;count only as an on/off switch count used for lists of things
Data sources vs inputs 1 A dependency's identity is taken as an input; facts about it are looked up Asking for facts that can disagree with the dependency (an ID and its CIDR)
File layout 1 Variables, outputs and resources each in their place; split by concern as the module grows One file holding everything; a large main.tf mixing concerns
Lifecycle meta-arguments 1 prevent_destroy only where no native protection exists;ignore_changes only for values changed outside IaC Lifecycle used instead of a native protection attribute; unconditional ignore_changes
Documentation 1 2: accurate, and sized to the module.1: accurate but too thin or so heavy it becomes noise. 0: missing, orany statement wrong or out of date
Deprecated and escape-hatch patterns 1 No deprecated resource forms; no unexplained null_resource /local-exec Legacy forms; shell escape hatches
Anti-patterns 1 None present An input that lets a consumer silently violate the module's own security posture; an error hidden by deleting a resource; calling a remote module

The judge reads these sections for context but does not grade them, so a defect never costs a module twice:

Doctrine section Rubric criteria
Insecure configurations G001 H1 ,H3 ; G002H1 ,H2 ,H7 ,H10 ; G003H1 –H4
Destructive defaults G001 H14 ; G002H3 –H5 ,H11
Unstated assumptions G001 A4 ; G002A9 (G003 has no item)
Tagging G001 H12 ; G002H8 ; G003H8
Versions B1 (all fixtures)
Provider declarations B1 ; G001H15 ; G002H9

How Claude Fable 5.1 did on iac-bench 2026-10: an overall composite of 86.9, scores per fixture, strengths, weaknesses and the patterns in its OpenTofu modules.

How Claude Haiku 5.5 did on iac-bench 2026-10: an overall composite of 68.0, scores per fixture, strengths, weaknesses and the patterns in its OpenTofu modules.

How Claude Opus 5.5 did on iac-bench 2026-10: an overall composite of 88.9, scores per fixture, strengths, weaknesses and the patterns in its OpenTofu modules.

── more in #ai-tools 4 stories · sorted by recency
── more on @iac-bench 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/iac-bench-2026-10-sc…] indexed:0 read:19min 2026-11-04 · —