Description
Ensure that the outputs of every AWS CloudFormation stack do not contain secrets such as passwords, API keys, access tokens or private keys. The name and value of each stack output are scanned for patterns that look like secrets. Stacks without outputs pass.
Rationale
Stack output values are shown in plain text to anyone who can view the stack in the console or call the CloudFormation API, can be read by other stacks when exported, and can end up in CI/CD logs. Secrets in outputs can be stolen and used for unauthorized API calls, privilege escalation and data exfiltration. Store credentials in AWS Secrets Manager or AWS Systems Manager Parameter Store, reference them through dynamic references, and use NoEcho for sensitive parameters.
Impact
Removes plain-text secrets from the stack details shown in the console and API
Prevents secrets from being shared with other stacks through exports
Applications or pipelines that read the secret from the stack output must be changed to read it from Secrets Manager or Parameter Store instead
An output cannot be removed while another stack imports it, and any secret found should be treated as exposed and rotated
Default Value
CloudFormation does not scan or hide output values. Outputs exist only if they are defined in the template, and their values are always shown in plain text.
Pre-Requisites
IAM permissions: cloudformation:DescribeStacks, cloudformation:GetTemplate, cloudformation:UpdateStack and cloudformation:ListImports, plus the permissions needed to update the resources in the stack
A copy of the stack template with the secret outputs removed
Agreement with the owner of each exposed credential to rotate it
Remediation
Test Plan
Console:
Sign in to the AWS Management Console at https://console.aws.amazon.com.
Open the CloudFormation console and select Stacks.
Select a stack and open the Outputs tab.
Review the output keys and values for passwords, API keys, tokens, private keys or connection strings with credentials.
Repeat for each stack in each region in use.
If any secret is found, follow the implementation steps.
CLI:
Show the outputs of all stacks in a region:
aws cloudformation describe-stacks --region <REGION> --query "Stacks[].[StackName,Outputs[].[OutputKey,OutputValue]]" --output json
A stack fails if any output key or value looks like a secret. Stacks without outputs pass.
Implementation Steps
Console:
Sign in to the AWS Management Console at https://console.aws.amazon.com.
Open the CloudFormation console, select the stack and open the Template tab to get the current template.
Edit the template to remove each output that contains a secret. If the value is needed elsewhere, store it in Secrets Manager and output only the secret's ARN.
If the output is exported, first update the stacks that import it, because an output cannot be removed while it is imported.
Select the stack and choose Update, then Replace current template, and upload the edited template.
Choose Next through the wizard, keep the existing parameter values, and choose Submit.
Open the Outputs tab and check that the secret is no longer shown.
Rotate the exposed credentials at their source.
Repeat for each affected stack in each region in use.
CLI:
Update the stack with the edited template. If the stack has parameters, add --parameters ParameterKey=<PARAMETER_NAME>,UsePreviousValue=true for each one, and add --capabilities CAPABILITY_NAMED_IAM if the stack creates IAM resources:
aws cloudformation update-stack --region <REGION> --stack-name <STACK_NAME> --template-body file://template-without-secret-outputs.yaml
Backout Plan
Before making changes, save the current template from the Template tab, or with the following command (for templates written in YAML):
aws cloudformation get-template --region <REGION> --stack-name <STACK_NAME> --query "TemplateBody" --output text > template-backup.yaml
To roll back:
Sign in to the AWS Management Console at https://console.aws.amazon.com.
Open the CloudFormation console and select the stack.
Choose Update, then Replace current template, and upload the saved template.
Choose Next through the wizard, keep the existing parameter values, and choose Submit.
CLI:
aws cloudformation update-stack --region <REGION> --stack-name <STACK_NAME> --template-body file://template-backup.yaml
Note: rolling back exposes the secrets in the stack outputs again. If the credentials have already been rotated, the old values will no longer work.
Reference
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html
https://docs.aws.amazon.com/secretsmanager/latest/userguide/best-practices.html
https://docs.aws.amazon.com/cli/latest/reference/cloudformation/update-stack.html