TerraformPilot

Troubleshooting

Fix Terraform Error - Output Refers to Sensitive Value

Fix the Terraform output refers to sensitive values error. Covers sensitive outputs, nonsensitive function, module outputs, and secrets management patterns.

LLuca Berton2 min read

Quick Answer

#

Add sensitive = true to the output block, or use nonsensitive() if you intentionally want to expose the value. Terraform prevents accidental exposure of sensitive data in outputs.

The Error

#
Error: Output refers to sensitive values
 
  on outputs.tf line 1:
  1: output "db_connection_string" {
 
To reduce the risk of accidentally exporting sensitive data that was
intended to be only internal, Terraform requires that any root module
output containing sensitive data be explicitly marked as sensitive.

What Causes This Error

#

Terraform tracks which values are "sensitive" — marked either in variable definitions or by provider attributes. When you reference a sensitive value in an output without marking the output as sensitive, Terraform blocks it to prevent accidental exposure.

Common Triggers

#
# Variable marked sensitive
variable "db_password" {
  type      = string
  sensitive = true
}
 
# Provider attribute marked sensitive (automatic)
# aws_db_instance.main.password is always sensitive
 
# Output referencing sensitive value without sensitive = true
output "db_password" {
  value = var.db_password  # ERROR — sensitive value in non-sensitive output
}

How to Fix It

#

Solution 1: Mark the Output as Sensitive

#
output "db_connection_string" {
  value     = "postgresql://${var.db_user}:${var.db_password}@${aws_db_instance.main.endpoint}/mydb"
  sensitive = true
}
 
output "db_password" {
  value     = var.db_password
  sensitive = true
}
 
# Access the value later:
# terraform output -json db_password
# terraform output -raw db_password

Solution 2: Use nonsensitive() for Intentional Exposure

#

If the value isn't actually secret (e.g., a generated resource name):

output "db_endpoint" {
  # The endpoint itself isn't secret, but it's derived from a sensitive resource
  value = nonsensitive(aws_db_instance.main.endpoint)
}
 
# Only use nonsensitive() when you've verified the value isn't actually secret

Solution 3: Separate Sensitive and Non-Sensitive Outputs

#
# Non-sensitive outputs
output "db_endpoint" {
  value       = aws_db_instance.main.endpoint
  description = "Database endpoint"
}
 
output "db_port" {
  value       = aws_db_instance.main.port
  description = "Database port"
}
 
# Sensitive outputs
output "db_password" {
  value       = aws_db_instance.main.password
  sensitive   = true
  description = "Database master password"
}
 
output "db_connection_string" {
  value     = "postgresql://${var.db_user}:${random_password.db.result}@${aws_db_instance.main.endpoint}:${aws_db_instance.main.port}/mydb"
  sensitive = true
}

Solution 4: Use Secrets Manager Instead of Outputs

#

For production, store secrets in a secrets manager:

resource "random_password" "db" {
  length  = 24
  special = true
}
 
resource "aws_secretsmanager_secret" "db_password" {
  name = "${var.project}-db-password"
}
 
resource "aws_secretsmanager_secret_version" "db_password" {
  secret_id     = aws_secretsmanager_secret.db_password.id
  secret_string = random_password.db.result
}
 
# Output the secret ARN (not sensitive) instead of the password
output "db_password_secret_arn" {
  value       = aws_secretsmanager_secret.db_password.arn
  description = "ARN of the Secrets Manager secret containing the DB password"
}

Solution 5: Handle Sensitive Values in Module Outputs

#

When a child module outputs sensitive values:

# modules/database/outputs.tf
output "password" {
  value     = random_password.db.result
  sensitive = true
}
 
# Root module
module "database" {
  source = "./modules/database"
}
 
# Must also be sensitive in root
output "db_password" {
  value     = module.database.password
  sensitive = true
}

Accessing Sensitive Outputs

#
# Sensitive outputs show as <sensitive> in normal output
terraform output
# db_password = <sensitive>
 
# Use -json to see the actual value
terraform output -json db_password
 
# Use -raw for plain text (scripts)
terraform output -raw db_password
 
# In CI/CD pipelines
DB_PASS=$(terraform output -raw db_password)

Troubleshooting Checklist

#
  1. ✅ Which value is sensitive? Check the error message line number
  2. ✅ Should the output be sensitive? Add sensitive = true
  3. ✅ Is the value actually not secret? Use nonsensitive()
  4. ✅ Should you store it in Secrets Manager instead?
  5. ✅ Are module outputs also marked sensitive?

Prevention Tips

#
  • Always mark outputs containing secrets as sensitive = true
  • Store secrets in Secrets Manager/Vault — don't pass them through Terraform outputs
  • Use random_password for generated credentials — automatically marked sensitive
  • Review outputs before adding — ask "would I show this in a log?"
  • Use .terraform.tfstate encryption — state files contain all output values in plaintext
#

Conclusion

#

Terraform blocks sensitive values from appearing in non-sensitive outputs to prevent accidental exposure. Add sensitive = true to the output, use nonsensitive() only for values that aren't actually secret, and consider storing passwords in AWS Secrets Manager or HashiCorp Vault instead of passing them through Terraform outputs.

#outputs#sensitive#security

Share this article