Plaintext AWS Credentials In Environment Variables
More Info:
This rule checks AWS CodeBuild projects for environment variables that contain plaintext AWS credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY). Storing AWS credentials in plaintext within environment variables poses a significant security risk, as it can lead to unauthorized access if the credentials are exposed. It is recommended to use IAM roles or encrypted secrets management services like AWS Secrets Manager to handle credentials securely.
Risk Level
High
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- Cloudanix Best Practice
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Using Console
To remediate “Plaintext AWS Credentials In Environment Variables” for an AWS CodeBuild project using the AWS Console:
-
Open the CodeBuild project
- Sign in to the AWS Management Console.
- Go to CodeBuild.
- In Build projects, click the relevant project name.
-
Edit environment settings
- On the project detail page, choose Edit (top right).
- Scroll to the Environment section.
- Under Environment variables, identify any variables that contain:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN- Or any other credentials / secrets in plain text.
-
Remove plaintext AWS credentials
- For each environment variable that contains an AWS key or secret in Plaintext:
- Click the trash bin icon to delete it or
- If you must keep a variable name, clear the plaintext value and plan to replace it with a secure reference (Secrets Manager/Parameter Store).
- For each environment variable that contains an AWS key or secret in Plaintext:
-
Use IAM roles instead of access keys (preferred)
- In the same Environment section, under Service role, ensure that:
- The CodeBuild project has an appropriate service role (e.g.,
codebuild-your-project-service-role) with required permissions attached.
- The CodeBuild project has an appropriate service role (e.g.,
- If needed, open the role in IAM (link next to role name) and:
- Attach or adjust IAM policies to grant the build the permissions it needs.
- With a correctly configured service role, you no longer need
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYin environment variables.
- In the same Environment section, under Service role, ensure that:
-
(Optional) Use secure environment variables via Secrets Manager or Parameter Store If you must keep non-AWS secrets (e.g., API keys, passwords):
-
Create secret/parameter first:
- For Secrets Manager:
- Go to AWS Secrets Manager → Store a new secret.
- Add your secret value.
- Note the Secret name.
- For Systems Manager Parameter Store:
- Go to Systems Manager → Parameter Store → Create parameter.
- Type: SecureString, put your secret value.
- Note the Parameter name (e.g.
/myapp/DB_PASSWORD).
- For Secrets Manager:
-
Reference it in CodeBuild:
- Back in the CodeBuild project Edit page → Environment → Environment variables.
- Click Add environment variable.
- Set:
- Name: the variable name (e.g.,
DB_PASSWORD). - Type:
- Parameter (for Parameter Store) or
- Secrets Manager (for Secrets Manager).
- Value:
- For Parameter Store: the parameter name (e.g.,
/myapp/DB_PASSWORD). - For Secrets Manager: the secret name or ARN.
- For Parameter Store: the parameter name (e.g.,
- Name: the variable name (e.g.,
- Ensure the CodeBuild service role has permissions to access:
ssm:GetParameter(andDecrypt) for Parameter Store, orsecretsmanager:GetSecretValuefor Secrets Manager.
-
-
Save the changes
- Scroll down and click Update environment (if shown), then Save or Update at the bottom of the page.
-
Verify
- Start a new build of the project.
- Check Build logs to confirm:
- No credentials are being echoed or logged.
- The build still has the required access via IAM role or secure secrets references.
This removes plaintext AWS credentials from CodeBuild environment variables and replaces them with the proper, least-privilege IAM role and secure secret storage.
Using CLI
Below are concise, CLI-focused steps to remediate plaintext AWS credentials in AWS CodeBuild project environment variables.
1. Identify Projects With Plaintext Credentials
Check your CodeBuild projects’ environment variables for AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc.
# List all projects
aws codebuild list-projects
# For each project, inspect environment variables
aws codebuild batch-get-projects \
--names MyProjectName
Look in .projects[0].environment.environmentVariables for any plaintext AWS creds or other secrets.
2. Decide the Correct Remediation Pattern
Prefer IAM role over environment credentials:
- Let the CodeBuild service role or an attached instance role have the necessary permissions.
- For non-AWS secrets, use SSM Parameter Store or Secrets Manager with
type=PARAMETER_STOREorSECRETS_MANAGER.
You must first:
- Create/identify an IAM role with proper permissions, and ensure CodeBuild uses it (
serviceRole). - Or store secrets in SSM/Secrets Manager and grant CodeBuild role permission to read them.
3. Remove Plaintext AWS Credentials From Environment
- Get the existing project configuration:
aws codebuild batch-get-projects \
--names MyProjectName \
--query 'projects[0]' > project.json
- Edit
project.json:- Remove any environment variables like:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN- Any other hardcoded credentials.
- Keep the structure under
"environment"the same. - Do not touch required fields (name, source, artifacts, serviceRole, etc.) other than editing/removing env vars.
- Remove any environment variables like:
Example environment section before:
"environment": {
"type": "LINUX_CONTAINER",
"image": "aws/codebuild/standard:7.0",
"computeType": "BUILD_GENERAL1_SMALL",
"environmentVariables": [
{ "name": "AWS_ACCESS_KEY_ID", "value": "AKIA..." },
{ "name": "AWS_SECRET_ACCESS_KEY", "value": "abc123..." },
{ "name": "OTHER_VAR", "value": "some-value" }
],
"privilegedMode": false
}
Example after (remove the credential vars):
"environment": {
"type": "LINUX_CONTAINER",
"image": "aws/codebuild/standard:7.0",
"computeType": "BUILD_GENERAL1_SMALL",
"environmentVariables": [
{ "name": "OTHER_VAR", "value": "some-value" }
],
"privilegedMode": false
}
- Update the project using the modified JSON:
aws codebuild update-project \
--name MyProjectName \
--source "$(jq '.source' project.json)" \
--artifacts "$(jq '.artifacts' project.json)" \
--environment "$(jq '.environment' project.json)" \
--service-role "$(jq -r '.serviceRole' project.json)" \
--description "$(jq -r '.description // empty' project.json)" \
--timeout-in-minutes "$(jq -r '.timeoutInMinutes // 60' project.json)" \
--queued-timeout-in-minutes "$(jq -r '.queuedTimeoutInMinutes // 480' project.json)" \
--cache "$(jq '.cache // {}' project.json)" \
--encryption-key "$(jq -r '.encryptionKey // empty' project.json)" \
--badge-enabled "$(jq -r '.badge.badgeEnabled // false' project.json)" \
--logs-config "$(jq '.logsConfig // {}' project.json)" \
--vpc-config "$(jq '.vpcConfig // {}' project.json)"
Adjust fields to match what exists in project.json; omit any args your project doesn’t use.
4. (Optional) Replace With Secure References
If you still need to pass non-AWS secrets to the build:
Using SSM Parameter Store
- Store secret:
aws ssm put-parameter \
--name "/MyApp/DbPassword" \
--value "SuperSecretPassword" \
--type "SecureString"
-
Grant CodeBuild role access (
ssm:GetParameteron that parameter). -
Add a parameter store env var (edit
project.jsonagain):
"environmentVariables": [
{
"name": "DB_PASSWORD",
"value": "/MyApp/DbPassword",
"type": "PARAMETER_STORE"
}
]
- Re-run
aws codebuild update-projectas above.
Using Secrets Manager
- Create secret:
aws secretsmanager create-secret \
--name "MyApp/DbCredentials" \
--secret-string '{"username":"dbuser","password":"SuperSecretPassword"}'
-
Grant CodeBuild role
secretsmanager:GetSecretValueon that secret. -
Add env var with
type=SECRETS_MANAGER.
5. Verify
Run a build and confirm:
- No plaintext AWS credentials appear in:
- Project configuration
- Build logs
- CloudTrail
StartBuildevents’ environment variables.
- Build still succeeds, and IAM role/secret references are functioning.
Using Python
To remediate this, you must remove plaintext credentials from the CodeBuild environment and instead pull them securely at runtime (e.g., from IAM role, Secrets Manager, or SSM Parameter Store). Below are step-by-step instructions, including Python (boto3) examples.
1. Understand what “plaintext credentials” means in CodeBuild
In CodeBuild, this is bad:
- Environment variable type:
PLAINTEXT - Name:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, etc. - Value: literal credential string
You want no static AWS keys in environment variables at all.
2. Prefer IAM role over any stored credentials
First choice: let CodeBuild’s service role have permissions to what the build needs.
Then your build just uses the normal AWS SDK with no keys in env vars.
- Go to IAM → Roles.
- Find the role used by your CodeBuild project (shown under the project’s Service role).
- Attach or adjust a policy to allow the resources/actions it needs (e.g., S3, ECR, etc.).
- In your buildspec/code, do not set any AWS credentials. Just use the SDK normally.
No Python code change needed other than removing explicit credential usage.
3. If you must store secrets: use Secrets Manager or SSM
If (for some reason) you need non-IAM secrets (API keys, passwords, etc.):
3.1 Store the secret
Example with Secrets Manager:
aws secretsmanager create-secret \
--name my/api/secret \
--secret-string '{"api_key":"YOUR_API_KEY"}'
Give the CodeBuild role permission to read this secret:
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:my/api/secret-*"
}
4. Remove plaintext environment variables from the CodeBuild project
4.1 Using the AWS Console
- Go to CodeBuild → Build projects → Your project.
- Click Edit.
- Under Environment → Additional configuration → Environment variables:
- Delete any variables like
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, etc. of typePlaintext.
- Delete any variables like
- Save.
4.2 Using Python (boto3) to remove/redesign env vars
This example:
- Fetches the project config
- Filters out sensitive plaintext variables
- Optionally replaces them with references to SSM/Secrets Manager (type
PARAMETER_STOREorSECRETS_MANAGER)
import boto3
codebuild = boto3.client("codebuild")
project_name = "your-project-name"
# 1. Get current project configuration
resp = codebuild.batch_get_projects(names=[project_name])
project = resp["projects"][0]
env = project["environment"]
current_env_vars = env.get("environmentVariables", [])
# 2. Filter out plaintext AWS credentials
SENSITIVE_NAMES = {
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"AWS_SECURITY_TOKEN",
}
new_env_vars = [
v for v in current_env_vars
if not (v["type"] == "PLAINTEXT" and v["name"] in SENSITIVE_NAMES)
]
# OPTIONAL: add secure references instead of plaintext values
# Example: pulling an API key from Secrets Manager
# new_env_vars.append({
# "name": "MY_API_SECRET",
# "value": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:my/api/secret-XXXX",
# "type": "SECRETS_MANAGER"
# })
env["environmentVariables"] = new_env_vars
# 3. Call update_project with modified environment
update_args = {
"name": project_name,
"description": project.get("description"),
"source": project["source"],
"artifacts": project["artifacts"],
"environment": env,
"serviceRole": project["serviceRole"],
}
# Preserve optional keys if present
optional_keys = [
"vpcConfig", "timeoutInMinutes", "queuedTimeoutInMinutes", "badgeEnabled",
"logsConfig", "cache", "fileSystemLocations", "buildBatchConfig",
"concurrentBuildLimit", "encryptionKey", "secondarySources",
"secondaryArtifacts", "sourceVersion"
]
for k in optional_keys:
if k in project:
update_args[k] = project[k]
codebuild.update_project(**update_args)
print("Updated project; plaintext AWS credentials removed from environment variables.")
5. Accessing secrets or AWS from your build (Python example)
5.1 Using IAM role (no env vars)
buildspec.yml example:
version: 0.2
phases:
install:
commands:
- pip install boto3
build:
commands:
- python build_script.py
build_script.py:
import boto3
s3 = boto3.client("s3") # uses CodeBuild role automatically
for b in s3.list_buckets()["Buckets"]:
print(b["Name"])
No credentials set anywhere.
5.2 Using Secrets Manager at runtime (if needed)
buildspec.yml:
version: 0.2
phases:
install:
commands:
- pip install boto3
build:
commands:
- python build_script.py
build_script.py:
import boto3
import json
import os
secret_arn = os.getenv("MY_API_SECRET") # set as SECRETS_MANAGER env var if needed
secrets_client = boto3.client("secretsmanager")
secret_value = secrets_client.get_secret_value(SecretId=secret_arn)
secret_dict = json.loads(secret_value["SecretString"])
api_key = secret_dict["api_key"]
print("Using API key (not printed here in real code).")
Summary
- Remove all plaintext AWS credentials from CodeBuild environment variables (console or boto3).
- Grant needed permissions via the CodeBuild IAM role.
- For non-IAM secrets, use Secrets Manager or SSM and fetch them at runtime in your Python build code.
Using Terraform
resource "aws_codebuild_project" "THIS_PROJECT" {
name = "REPLACE_WITH_PROJECT_NAME"
service_role = aws_iam_role.codebuild_role.arn
# Other existing configuration for the project goes here:
# description = "..."
# source { ... }
# artifacts { ... }
# vpc_config { ... }
# logs_config { ... }
# etc.
environment {
compute_type = "REPLACE_WITH_COMPUTE_TYPE" # e.g. BUILD_GENERAL1_SMALL
image = "REPLACE_WITH_BUILD_IMAGE" # e.g. aws/codebuild/standard:7.0
type = "LINUX_CONTAINER"
privileged_mode = false
image_pull_credentials_type = "CODEBUILD"
# KEEP ONLY NON-SENSITIVE ENV VARS HERE.
# Any existing environment_variable blocks whose name was
# "AWS_ACCESS_KEY_ID" or "AWS_SECRET_ACCESS_KEY" must be removed
# from Terraform instead of being set to plaintext values.
environment_variable {
name = "EXAMPLE_NON_SENSITIVE_VAR"
value = "EXAMPLE_VALUE"
type = "PLAINTEXT"
}
# For secrets, prefer:
# environment_variable {
# name = "SECRET_FROM_SSM"
# value = "REPLACE_WITH_SSM_PARAMETER_NAME"
# type = "PARAMETER_STORE"
# }
#
# or:
# environment_variable {
# name = "SECRET_FROM_SECRETS_MANAGER"
# value = "REPLACE_WITH_SECRETS_MANAGER_SECRET_ID_OR_ARN"
# type = "SECRETS_MANAGER"
# }
}
}
resource "aws_iam_role" "codebuild_role" {
name = "REPLACE_WITH_CODEBUILD_ROLE_NAME"
assume_role_policy = data.aws_iam_policy_document.codebuild_assume_role.json
}
data "aws_iam_policy_document" "codebuild_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["codebuild.amazonaws.com"]
}
}
}
This change does not force replacement of the aws_codebuild_project resource; it updates the existing project’s environment to remove any environment_variable blocks named AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY. Be careful to preserve all other needed environment variables when editing.
Verification with terraform plan should show the aws_codebuild_project resource being updated, with the environment[0].environment_variable entries for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY being removed and no other unintended changes.