Safeguard
Security Guides•

Does a Terraform Git module without ref follow the default branch?

Yes. A Git module source with no ref uses the default branch at HEAD, and the version argument only works for registry modules. Here is the safe fix.

Safeguard Security Team
4 min read

Yes. For a module in GitHub, Bitbucket or another Git repository, Terraform clones and uses the default branch referenced by HEAD unless you add a ref. The version argument does not apply to Git sources, so a constraint you wrote there will not protect you. Pin the ref to a tag or a full commit hash.

What the documentation says

Terraform's module documentation states that if you are using modules from a registry, you can add the version argument. If you use modules hosted in GitHub, Bitbucket or another Git repository, Terraform clones the default branch referenced by HEAD. You can add a ref query parameter with any value that git checkout accepts: a branch, a SHA-1 hash or a tag.

The module block reference adds that the version argument is only available for modules listed in a registry. It sits next to count, for_each, providers and depends_on in the list of arguments, so it is easy to assume it works everywhere.

Why this catches teams out

A common pattern is a module source that points at a company repository, which works fine for months. Nothing in the file says the code can change. Then someone merges to the default branch of the module repository, and the next init in a fresh workspace picks up that change.

A few things make it worse:

  • The lock file records provider versions and checksums, not module contents, so it does not protect module code. See what does the Terraform lock file protect.
  • Modules are installed at init, into a hidden subdirectory of the working directory, so an old cached copy can differ from a fresh checkout.
  • A plan from a laptop and a plan in CI can differ if their module copies came from different moments.

The fix, in order of strength

  1. Add ref with a tag, such as a version tag, to every Git module source.
  2. Protect tags in the module repository so they cannot be moved or deleted by most users.
  3. For critical modules, use a full commit hash in ref instead, which cannot change meaning.
  4. Better still for shared modules, publish to a private registry and use version constraints there. See pin Terraform module sources: registry version or Git ref.

Example with a tag:

module "vpc" {
  source = "git::https://example.com/vpc.git?ref=v1.2.0"
}

Example with a commit:

module "storage" {
  source = "git::https://example.com/storage.git?ref=51d462976d84fdea54b47d80dcabbf680badcdb8"
}

Both forms appear in the documentation.

Finding the offenders

Search your repositories for source lines containing git::, github.com or bitbucket.org that lack a ref. A simple pattern search in CI that fails on a missing ref is a cheap guardrail. Run it on every pull request that touches .tf files.

Also check where the version argument appears next to a non-registry source. It is a sign the author expected pinning that is not happening.

When variables appear in sources

The documentation notes that any input variable referenced in a module source or version must declare const as true, because modules are installed at initialization when variable values are not yet available. If you build source strings from variables, keep them constant and reviewed.

Where a scanner fits

Unpinned module sources are a configuration finding, and the modules themselves can contain risky resources. Safeguard's policy gates can enforce a rule like requiring a ref, and SBOM and dependency scanning help inventory what you depend on. Confirm your scanner parses Terraform sources. Free scan: gold.safeguard.sh/scan.

Quick check

Can I use version with a Git module source?

No. The module block reference says version is only available for modules listed in a registry. Use ref for Git sources.

Is a short commit hash fine in ref?

The documentation says ref accepts any value that git checkout supports, but use the full 40 character hash to avoid ambiguity.

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.