VNX-TF-008 – Terraform AWS Provider with Hardcoded Static Credentials

Overview

This rule flags Terraform .tf, .tofu and .tfvars files where access_key, aws_access_key, aws_access_key_id or AWS_ACCESS_KEY_ID is assigned a quoted AKIA/ASIA key id, or secret_key, aws_secret_key, aws_secret_access_key or AWS_SECRET_ACCESS_KEY is assigned a quoted 40-character secret. Values from variables, data sources or interpolation, empty strings, placeholders (runs of X, values in one case with no digit) and comments are not reported. AWS credentials hardcoded directly in Terraform files are committed to version control and exposed to everyone who has read access to the repository.

Unlike environment-injected credentials or IAM instance roles, hardcoded credentials in .tf files are static: they do not rotate, they do not expire automatically, and they persist in git history indefinitely. An attacker who obtains these credentials can authenticate to AWS from anywhere on the internet, using the full permissions of the associated IAM user.

This rule corresponds to CWE-798: Use of Hard-coded Credentials.

Severity: High | CWE: CWE-798 – Use of Hard-coded Credentials

Why This Matters

AWS access keys for IAM users are long-lived credentials that provide persistent, programmatic access to AWS resources. Unlike temporary credentials issued by IAM roles (which expire after hours), IAM user access keys remain valid until explicitly rotated or deleted. An attacker who extracts an access key from a Terraform file can use it indefinitely unless the key is revoked.

Terraform state files and configuration files are frequently stored in version control systems, CI/CD platform logs, and artifact stores — all of which may have weaker access controls than the production infrastructure they manage. A single compromised developer laptop or CI system that has access to the repository is sufficient to expose hardcoded credentials to an attacker.

Compromised Terraform provider credentials are particularly high-value because they typically have broad permissions: Terraform needs to create, modify, and delete infrastructure resources, so the associated IAM user or role often has significant access. An attacker using these credentials can provision additional infrastructure (for cryptomining), exfiltrate data from S3 and databases, modify security group rules to create backdoors, and cover their tracks by modifying CloudTrail settings.

What Gets Flagged

provider "aws" {
  region     = "us-west-2"
  access_key = "AKIA................"   # FLAGGED: literal key id
  secret_key = "........................................"   # FLAGGED
}

# terraform.tfvars
aws_access_key = "AKIA................"   # FLAGGED

Not flagged: access_key = var.aws_access_key, profile = "deploy", or aws_access_key = "AKIAXXXXXXXXXXXXXXXX" (a placeholder).

Remediation

  1. Use IAM instance roles or task roles. When Terraform runs on an EC2 instance, ECS task, Lambda function, or CodeBuild project, the AWS provider automatically discovers credentials from the instance metadata service. No credentials need to be specified in the provider block:
# SAFE: no credentials in provider — discovered from instance role
provider "aws" {
  region = "us-east-1"
  # credentials loaded from IAM role via instance metadata
}
  1. Use environment variables for local development and CI/CD. The AWS provider reads AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from the environment automatically:
# SAFE: inject credentials from environment — not committed to source
export AWS_ACCESS_KEY_ID="$(vault read -field=access_key aws/creds/deploy)"
export AWS_SECRET_ACCESS_KEY="$(vault read -field=secret_key aws/creds/deploy)"
terraform apply
  1. Use short-lived credentials from AWS IAM Identity Center (SSO) or Vault’s AWS secrets engine to ensure credentials rotate automatically and are never long-lived static keys.

  2. Revoke the hardcoded credentials immediately in the AWS IAM console, then rewrite git history to remove them using git filter-repo or BFG Repo-Cleaner.

References