Safeguard
Developer Tools•

What does a Terraform version constraint like ~> 1.2 actually allow?

The ~> operator lets only the right-most version part rise. See what ~> 1.0.4 and ~> 1.1 allow, and how to choose constraints for providers and modules.

Safeguard Security Team
3 min read

The ~> operator allows only the right-most version component to increase. So ~> 1.1 allows 1.2 and 1.10 but not 2.0, and ~> 1.0.4 allows 1.0.5 and 1.0.10 but not 1.1.0. It is a ceiling that stops major jumps.

The operators in one table

OperatorMeaningExample
= or noneExactly one version1.2.0
!=Excludes one version!= 1.2.3
>, >=, <, <=Comparison>= 1.2.0
~>Right-most part may increase~> 1.1

Several conditions in one string are joined by commas, and Terraform uses versions that meet all applicable constraints. A range such as >= 1.2.0, < 2.0.0 allows 1.2.0 and newer but nothing from 2.0.0.

Where constraints apply

Version constraints work for modules, provider requirements and the required_version setting. For plugins and modules, Terraform uses the newest installed version that meets the constraint, and downloads the newest acceptable one if none is installed.

That last point matters for security. A loose constraint on a remote module means a new release can enter your next terraform init without any change in your repository, because Terraform does not remember module selections. For providers the lock file holds the selection, so a loose constraint is less risky, until someone runs -upgrade.

Choosing a constraint

  1. For modules from a registry, use an exact version or a tight ~> and update by pull request.
  2. For providers, use ~> on the major version and rely on the lock file for the exact pick.
  3. For required_version, state the oldest Terraform version you test with and cap the next major.
  4. Never leave a module version argument off when the source is a registry. The documentation recommends constraining the acceptable versions explicitly.

Pre-release versions

A pre-release version has a suffix, such as 1.2.0-beta. To select one, set the exact version with the = operator. Constraints written as ranges will not pick it up.

Quick example

terraform {
  required_version = ">= 1.9, < 2.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Read it as: any 5.x release of the provider, from the public registry namespace hashicorp, with the Terraform CLI at 1.9 or later but below 2.0.

Quick check

Does ~> 1.0 allow 1.9?

Yes. With two components, the right-most one (the minor number) can rise, so 1.9 is allowed but 2.0 is not.

Is an exact version always safest?

It gives the most predictable result, but you then need a routine for upgrades and security fixes.

Does the constraint replace the lock file?

No. Constraints say what is acceptable. The lock file records what was selected.

Safeguard offers SBOM and dependency scanning and policy gates that can block a pull request on findings, and you can try a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.