Terraform Variable Defaults Checker
Review Terraform variable blocks for risky defaults, secret-like fallbacks, type mismatches, nullable surprises, and prioritized fixes.| {{ header }} | Copy |
|---|---|
| {{ cell }} | |
|
No {{ tab.label.toLowerCase() }} rows
Load a sample or adjust the source and policy until this artifact has exportable rows.
|
Introduction:
Terraform variables are the contract between a module author and the caller who supplies environment-specific values. A module may create complex infrastructure, but its variable blocks are often the first place a reviewer can see what must be chosen, what is optional, what type is expected, and what fallback Terraform will use when the caller says nothing.
Defaults make modules easier to test and reuse when they describe a safe ordinary case. An empty tag map, a disabled feature flag, or a conservative list of allowed services can reduce boilerplate without hiding caller intent. The same idea becomes risky when a default carries a credential, has the wrong type, looks computed, or lets a module appear deployable without a value that should be chosen per environment.
Required inputs are not a defect by themselves. A VPC ID, customer name, account alias, workspace slug, region, or token may belong to the caller because the module author cannot choose one meaningful value for every deployment. The review question is whether the missing default is intentional, documented, typed, and safe for the module's audience.
- Default
- A fallback value Terraform uses when no higher-precedence value is supplied.
- Required input
- A variable without a default, so the caller must provide the value before planning or applying.
- Sensitive
- A redaction hint for CLI and UI output. Sensitive values still need careful state and plan handling.
- Nullable
- A setting that decides whether a caller can pass
null, including cases wherenulloverrides a non-null default.
Terraform also has a value-precedence model. Caller-supplied values from command-line flags, variable files, environment variables, or managed workspaces can override the declared default. The default still matters because it is the final fallback, the visible contract in source, and often the value copied into examples, tests, and release notes.
A default audit cannot prove that a whole Terraform project is correct. It catches review signals inside variable declarations: missing type constraints, unclear required inputs, secret-like names, concrete sensitive fallbacks, nullable surprises, validation gaps, deprecated inputs, and default expressions that do not belong in variable blocks.
How to Use This Tool:
Start with the module or stack you want to review, then paste complete Terraform variable declarations from that scope.
- Enter a
Module or stack labelso copied rows, exports, and the audit snapshot can be tied back to the repository path, stack, release, or pull request. - Choose
Default policy. UseModule contractwhen required inputs are expected,Default hygienewhen safe non-sensitive defaults are preferred, orStrict releasewhen a reusable release surface should avoid most required non-sensitive values.The policy changes how missing non-sensitive defaults are treated. It does not soften findings for secret-like defaults, type mismatches, or computed-looking defaults. - Set
Terraform targetto the oldest Terraform version the module must support. The Terraform 1.10+ option adds low-priority guidance for temporary sensitive variables that may be eligible forephemeral = true. - Paste Terraform or HashiCorp Configuration Language text into
Variables source, browse for a.tffile, or drop a supported text file onto the editor.Selected files are capped at 5 MB. If the source warning says no variable blocks were found or braces are unmatched, fix the paste before trusting the audit count. - Use
Risky sample,Clean sample, andTidy sourceonly to understand the output shape or normalize a paste. Replace samples with the real module text before making a review decision. - Read
Default Audit Snapshotfor the headline decision,Remediation Queuefor prioritized fixes,Variable Ledgerfor every parsed variable, andDefault Exposure Chartto see where severities cluster by default posture.
Interpreting Results:
The headline high-impact count includes critical and high findings. Treat it as a triage signal, not as the full amount of cleanup. One hardcoded token-like default can be more urgent than many low-priority description or validation suggestions.
Default coverage is descriptive. A low percentage can be healthy when a module intentionally requires environment-specific values. A high percentage can still be risky when one fallback is secret-like, a string is supplied for a numeric type, a default looks computed, or null can bypass a value that looked protective.
| Decision | Meaning | Practical response |
|---|---|---|
Blocked |
At least one critical finding is present, usually a sensitive default resembling a known access key, token, live secret prefix, or private key pattern. | Remove the value, rotate it if it may be real, and review related state, plan, and commit history outside the checker. |
High-impact review |
A high finding exists, such as a secret-like name without sensitivity, a concrete sensitive default, a non-literal default, a type mismatch, or a strict-release missing default. | Resolve the row or record a module-owner exception before broad reuse. |
Review defaults |
Medium findings are present, or the weighted score is at least 14. |
Check whether missing defaults are intentional and whether type constraints and descriptions are strong enough for callers. |
Polish contract |
Only low-priority findings are visible, such as missing descriptions, nullable cleanup, validation hints, deprecation notes, or Terraform 1.10+ ephemeral guidance. | Clean these up during module hardening or release preparation. |
Default posture clear |
The supported checks did not find a problem in the submitted variable blocks. | Still run Terraform validation, planning, policy checks, and normal code review for the full configuration. |
The Remediation Queue is sorted by severity, line number, and variable name. If the visible row limit hides findings, raise Finding row limit before handing results to another reviewer so the queue matches the source under review.
Technical Details:
A Terraform variable becomes optional when it has a default argument. If type is also declared, the fallback must convert to that type. Variable defaults are expected to be literal values, so references to other objects, interpolations, or function-like expressions belong in caller input, local values, resources, or other configuration blocks rather than in the variable default.
Sensitive handling has two separate concerns. sensitive = true redacts values in many Terraform outputs, while state and plan storage still need protection. Terraform 1.10 and later adds ephemeral variables for temporary values in supported contexts, so a short-lived provider token may need different handling from an ordinary non-secret module option.
Nullability can surprise module users. When a variable has a non-null default and nullable remains true, a caller can explicitly pass null and replace the fallback. That behavior is sometimes useful, but it should be intentional because it can weaken a default that looked protective during review.
Formula Core:
The audit score is a weighted sum of finding severities. Default coverage is the share of parsed variables that declare any default, including null defaults.
For example, one high finding and two low findings produce a risk score of 22 because high rows carry 18 points and low rows carry 2 points each. A module with 8 parsed variables and 5 defaults has 62.5% default coverage.
Rule Core:
| Severity | Weight | Representative conditions | Review action |
|---|---|---|---|
Critical |
40 |
A sensitive or secret-like default resembles a known access key, token, live secret prefix, or private key. | Remove the fallback, rotate the value if it may be real, and treat the module as blocked until reviewed. |
High |
18 |
Secret-like name without sensitivity, concrete sensitive default, non-literal default, type mismatch, or missing non-sensitive default under Strict release. |
Fix before broad release or document a narrow exception. |
Medium |
7 |
Missing type constraint, or missing non-sensitive default under Default hygiene. |
Clarify whether the caller contract is intentional. |
Low |
2 |
Missing description, nullable cleanup, validation suggestion, deprecation note, or Terraform 1.10+ ephemeral suggestion. | Polish the module contract and reduce future reviewer guesswork. |
Checks Applied to Each Variable:
| Check | Signal | Why it matters |
|---|---|---|
| Type contract | No type argument, or a default whose literal shape does not match the declared primitive or collection family. |
Callers get clearer errors when the accepted value shape is explicit and the default follows the same shape. |
| Description contract | No consumer-facing description text is present. | Required inputs are easier to trust when callers can see what value they must supply. |
| Sensitive value handling | A variable name looks secret-like, a sensitive variable has a concrete non-null default, or a Terraform 1.10+ sensitive variable may be eligible for ephemeral = true. |
Redaction and persistence choices change how safely credentials, keys, and session tokens move through Terraform runs. |
| Default literalness | The default appears to contain interpolation, a reference to another Terraform object, or a function-like expression. | Variable defaults should be literal fallbacks. Computed behavior is easier to reason about in locals, callers, or resources. |
| Validation need | Names or string defaults suggest constrained values such as CIDRs, regions, ports, ARNs, URLs, environments, modes, sizes, tiers, strategies, or service names. | A validation block can reject values that have the right type but the wrong domain shape. |
| Nullable behavior | A non-null default exists and nullable = false is absent. |
Passing null can override the fallback unless null is explicitly disallowed. |
| Deprecated input | A deprecated note is present on the variable. |
The fallback still needs to stay safe while callers migrate to the replacement input. |
The parser focuses on variable blocks, top-level arguments, nested validation counts, line numbers, and common literal forms. It does not evaluate a full Terraform configuration, provider schema, module call graph, variable precedence at runtime, policy engine, or plan output.
Privacy and Accuracy Notes:
The Terraform text you paste or load is processed in the browser after the page loads, and selected files are read locally by the page. Treat the editor as sensitive anyway because module labels, variable names, sample defaults, and comments can reveal environment details.
- Sensitive defaults are masked in result tables and exports, but the original source text remains visible in the editor until you remove it.
- Exports can include module labels, variable names, line numbers, evidence text, severity, and recommended actions.
- Known secret-pattern checks are deliberately conservative and incomplete. A value can be dangerous even when it does not match a built-in pattern.
- The review is text-based. Run
terraform validate, a real plan, policy checks, and normal code review before using the module in production.
Advanced Tips:
- Use
Module contractfor internal modules where required inputs are normal, then switch toStrict releasebefore publishing a broad reusable module. - Raise
Finding row limitwhen the summary says hidden findings exist, especially before copying a remediation queue into a pull request. - Review
Variable Ledgerrows withdefault truenullability when the fallback is meant to be protective. - Check the
Default Exposure Chartfor clusters of sensitive defaults, required inputs, or concrete defaults that may point to a module-wide style issue. - Use the Terraform 1.10+ target only when every consumer can actually use Terraform 1.10 or later and all ephemeral references are valid in context.
Worked Examples:
Required network input is intentional
A module takes vpc_id with type = string, a clear description, and no default. Under Module contract, that can remain a required input because the caller must choose the target network. Under stricter policies, the owner should still confirm that the missing default is part of the published interface.
Public module needs a safer fallback decision
A reusable module exposes region with type = string and no default. Strict release treats that as high priority because a broadly shared module may need a documented safe default or a stronger reason to force every caller to provide the value.
Secret-like default blocks handoff
A variable named admin_password has sensitive = true and a string default. The ledger marks the posture as a sensitive default, and the remediation row asks for the fallback to be removed. If the value resembles a known live-token pattern, the decision moves to Blocked.
Partial paste can hide findings
A variable block with a missing closing brace can stop part of the source from being parsed. Fix the source warning before using the audit snapshot, because the parsed variable count may be lower than the module actually contains.
FAQ:
Does every Terraform variable need a default?
No. Missing defaults are normal for values the caller must choose, such as network IDs, environment-specific names, credentials, and workspace-specific settings. The selected policy decides when a missing non-sensitive default becomes a finding.
Why are computed-looking defaults flagged?
Terraform variable defaults should be literal values. References to other objects, interpolations, and function-like expressions are better handled through caller input, local values, resources, or outputs where Terraform can evaluate them in the proper context.
Does sensitive = true make a default safe?
No. Sensitivity helps redact output, but sensitive values can still be stored in state or plan data unless they are handled with features and contexts that avoid persistence. A reusable secret-like default should usually be removed.
Why does Terraform 1.10 matter?
Terraform 1.10 introduced ephemeral variables for temporary values in supported contexts. When the target is Terraform 1.10 or later, sensitive variables receive low-priority guidance to consider ephemeral = true when the value is temporary and all references are valid ephemeral contexts.
Why does the checker warn about unmatched braces?
A partial or broken paste can stop variable blocks from being parsed correctly. Fix the source warning before relying on Variables parsed, Default coverage, or the exported remediation rows.
Can this replace Terraform validation?
No. This is a focused variable-default review. Terraform validation and planning are still needed to check full syntax, provider behavior, module calls, policy rules, and runtime values.
Glossary:
- Variable block
- A Terraform declaration that names an input and may include type, default, description, validation, sensitivity, nullability, and other settings.
- Default posture
- The review category for a variable's fallback state, such as required input, null default, empty default, concrete default, or sensitive default.
- Type constraint
- The accepted value shape for a variable, such as string, number, bool, list, set, map, object, tuple, or any.
- Sensitive
- A setting that asks Terraform to redact a value in many outputs, while still requiring careful state and plan protection.
- Ephemeral
- A Terraform 1.10+ setting for temporary values that can be omitted from state and plan files when used in supported contexts.
- Validation block
- A rule inside a variable block that rejects caller values that do not meet a condition.
- Nullable
- A setting that controls whether callers may assign
nullto the variable.
References:
- Input variables, HashiCorp Developer.
- Variable block reference, HashiCorp Developer.
- Manage sensitive data in your configuration, HashiCorp Developer.