Initializing Enclave...

How to Fix Terraform Provider Signature Verification Failed: Certificate Expired

Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 10 mins


TL;DR

  • What broke: HashiCorp's GPG signing certificate used to verify provider binaries has expired; terraform init and terraform providers mirror abort with a signature verification error, blocking all provider installs.
  • How to fix it: Flush the local plugin cache, import the current HashiCorp GPG public key (Key ID 72D7468F), and ensure your terraform binary is ≥ 1.4.x which ships with the refreshed keyring.
  • Fast path: Use our Client-Side Sandbox below to auto-refactor your provider_installation block and .terraformrc without leaking registry tokens or private module paths.

The Incident (What Does the Error Mean?)

Raw error output from terraform init:

│ Error: Failed to install provider
│
│ Error while installing hashicorp/aws v5.x.x: the current package for
│ registry.terraform.io/hashicorp/aws 5.x.x doesn't match any of the
│ checksums previously recorded in the dependency lock file.
│
│ HashiCorp release signature verification failed:
│ certificate expired: current time 2024-xx-xxTxx:xx:xxZ is after
│ 2024-xx-xxTxx:xx:xxZ

Immediate consequence: terraform init hard-fails. No provider is installed or upgraded. Every pipeline stage that calls init — including plan, apply, and drift-detection jobs — is dead. In airgapped or Terraform Enterprise environments using a local mirror, this can silently block the entire platform team until the keyring is manually refreshed.


The Attack Vector / Blast Radius

This is not a benign cert rotation annoyance. Here is the actual risk surface:

Supply-chain integrity gap. The GPG signature on provider zips is the only cryptographic guarantee that the binary you are about to execute inside your AWS/GCP/Azure account is the one HashiCorp shipped. When the certificate expires and your toolchain is misconfigured to skip verification instead of fail, you have silently disabled the entire supply-chain check. A compromised registry mirror or a MITM on an internal Artifactory proxy can now serve a backdoored provider binary — hashicorp/aws with exfiltration code — and Terraform will execute it with your AWS_ACCESS_KEY_ID in scope.

Blast radius by environment:

Scenario Risk
Developer workstation skips verification via skip_signature_verification workaround Full credential exfiltration risk on next apply
CI/CD runner patched with --insecure flag to unblock pipeline Every plan/apply job runs unverified binaries
Terraform Enterprise / TFE airgapped mirror not refreshed Entire organization blocked or running on stale, unverified cache

The cascading failure: Teams under pressure to unblock pipelines add skip_signature_verification = true to their .terraformrc. This config gets committed. It propagates across teams. Six months later, nobody remembers why it's there, and it never gets removed.


How to Fix It

Step 1 — Purge the stale plugin cache

# Nuke the local provider cache. This forces a clean re-download and re-verification.
rm -rf ~/.terraform.d/plugins
rm -rf .terraform/providers
rm .terraform.lock.hcl

Step 2 — Import the current HashiCorp GPG signing key

# HashiCorp's current release key. Verify the fingerprint out-of-band.
curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --import

# Confirm fingerprint: E8A0 32E0 94D8 EB4E A189 D270 DA41 8C88 A321 9F7B
gpg --fingerprint 72D7468F

Step 3 — Upgrade Terraform CLI

Terraform ≥ 1.4.x ships with the refreshed embedded keyring. If you cannot upgrade immediately, the GPG import above is sufficient for the short term.

# macOS
brew upgrade terraform

# Linux (tfenv)
tfenv install latest
tfenv use latest

# Verify
terraform version

Basic Fix — .terraformrc provider_installation block

# ~/.terraformrc

provider_installation {
-  filesystem_mirror {
-    path    = "/opt/terraform/providers"
-    include = ["registry.terraform.io/*/*"]
-  }
-  # WARNING: This was added to unblock CI. REMOVE THIS.
-  direct {
-    exclude = []
-  }
+  filesystem_mirror {
+    path    = "/opt/terraform/providers"
+    include = ["registry.terraform.io/hashicorp/*"]
+  }
+  direct {
+    include = ["registry.terraform.io/hashicorp/*"]
+  }
}

Enterprise Best Practice — Enforce signature verification in Terraform Enterprise / Atlantis

For airgapped TFE or a self-hosted registry mirror (Artifactory, Nexus), you must re-sign mirrored provider zips with your internal CA and register the public key in TFE's GPG key store. Never use skip_signature_verification.

# providers.tf — required_providers block

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
-     version = ">= 4.0"
+     version = "~> 5.50"  # Pin to a tested minor, not a floor. Prevents silent major upgrades.
    }
  }
+
+  # Lock file must be committed to VCS. Never .gitignore .terraform.lock.hcl
}
# For Terraform Enterprise: register the new GPG key via API, not manually.

# BAD: Manual key import on one node only.
- curl --header "Authorization: Bearer $TFE_TOKEN" \
-      --request POST \
-      --data '{"data":{"type":"gpg-keys"}}' \
-      https://tfe.internal/api/registry/private/v2/gpg-keys

# GOOD: Automate key rotation via your secrets pipeline (Vault + Terraform TFE provider)
+ resource "tfe_registry_gpg_key" "hashicorp_current" {
+   organization = var.tfe_org
+   ascii_armor   = file("${path.module}/keys/hashicorp-current.asc")
+ }

💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.


Prevention in CI/CD

1. Pin and verify the Terraform binary in CI

# .github/workflows/terraform.yml
- name: Setup Terraform
  uses: hashicorp/setup-terraform@v3
  with:
    terraform_version: "1.8.5"   # Explicit pin. Never use 'latest' in prod pipelines.
    terraform_wrapper: false

2. Checkov policy — block skip_signature_verification

# checkov/custom/check_no_skip_sig_verification.py
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck

# Scan .terraformrc files in your repo for the dangerous flag.
# Integrate into pre-commit and CI gate.

Or use a simpler grep gate in CI:

# Fail the pipeline if anyone committed the bypass flag.
if grep -r "skip_signature_verification" .; then
  echo "FATAL: skip_signature_verification found in repo. Remove it."
  exit 1
fi

3. Automate GPG key freshness check

# Add to your weekly platform health cron job.
KEY_EXPIRY=$(gpg --list-keys --with-colons 72D7468F | grep '^pub' | cut -d: -f7)
NOW=$(date +%s)
if [ "$KEY_EXPIRY" -lt "$NOW" ]; then
  echo "ALERT: HashiCorp GPG key expired. Rotate immediately."
  # Page on-call via PagerDuty/Opsgenie webhook here.
fi

4. OPA / Conftest policy for provider lock file

# policy/terraform_lock.rego
package terraform.lockfile

deny[msg] {
  # Ensure lock file exists and is not empty — catches teams deleting it to "fix" checksum errors.
  not input.provider
  msg := "DENY: .terraform.lock.hcl is missing or has no provider entries. Do not delete the lock file to bypass checksum errors."
}

Run in CI: conftest test .terraform.lock.hcl --policy policy/

Related Diagnostics

"Part of the Security Utility Matrix."

View all 140 Security Tools →