Does sensitive = true Fully Protect Your Data in Terraform?

Marking a Terraform variable or output as sensitive = true is a useful safety measure, but it is widely misunderstood. It does not provide complete protection for your secrets. Here is exactly what it does and does not do.

What sensitive = true Does

variable "db_password" {
  type      = string
  sensitive = true
}

output "db_connection_string" {
  value     = "postgres://admin:${var.db_password}@${aws_db_instance.main.endpoint}/app"
  sensitive = true
}

When marked sensitive, Terraform will:

  • Mask the value in terraform plan and terraform apply output as (sensitive value).
  • Suppress the value in terraform output unless you use -json or -raw.
  • Prevent the value from appearing in regular log output.
# Plan output with sensitive = true
+ password = (sensitive value)   # Value is hidden in terminal

What sensitive = true Does NOT Do

This is the critical part most engineers miss:

  • It does NOT encrypt the value in the state file.
  • It does NOT prevent the value from being read with terraform state pull.
  • It does NOT remove the value from the .tfstate file on disk.
# The password is stored in CLEARTEXT inside terraform.tfstate
{
  "resources": [
    {
      "instances": [
        {
          "attributes": {
            "password": "SuperSecretPassword123!"  # Fully visible in state file!
          }
        }
      ]
    }
  ]
}

How to Truly Secure Sensitive Data

1. Use a Remote Backend with Encryption at Rest

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true          # Server-side encryption
    kms_key_id     = "arn:aws:kms:us-east-1:123456789:key/abc-123"  # KMS key
    dynamodb_table = "terraform-lock"
  }
}

2. Restrict Access to the State File

# S3 bucket policy — restrict to only Terraform IAM role
{
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::my-terraform-state/*",
  "Condition": {
    "StringNotEquals": {
      "aws:PrincipalArn": "arn:aws:iam::123456789:role/terraform-role"
    }
  }
}

3. Avoid Storing Secrets in State at All

# Use a data source to fetch secrets at apply time instead of storing them
data "aws_secretsmanager_secret_version" "db_pass" {
  secret_id = "prod/db/password"
}

Key Takeaway

sensitive = true only masks values in CLI output and logs — it is a display-layer protection, not encryption. The secret is still stored as cleartext in your state file. For true security, use a remote backend with KMS encryption, restrict state file access via IAM policies, and source secrets from a secret manager at apply time.

(Visited 1 times, 1 visits today)