Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · CodeBuild

CodeBuild.3: CodeBuild S3 logs should be encrypted

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub CodeBuild.3 check?

CodeBuild.3 fails any project whose S3 build logs are not encrypted — specifically where logsConfig.s3Logs.status is ENABLED and encryptionDisabled is true. It is change-triggered, backed by the AWS Config rule codebuild-project-s3-logs-encrypted, so it re-evaluates on every config change.

Why does CodeBuild.3 matter?

Build logs are rarely as innocuous as they look — they routinely echo source repository paths, dependency URLs, signed artifact locations, and, when a build misbehaves, fragments of credentials, tokens, and connection strings printed to stdout. Encryption at rest means anyone who reaches the raw S3 object but is not authorised through AWS still cannot read it.

How do I fix CodeBuild.3?

  1. List all projects and inspect logsConfig.s3Logs for any where status is ENABLED and encryptionDisabled is true.
  2. Re-enable encryption with update-project, setting encryptionDisabled to false while preserving the existing status and location.
  3. Optionally point the log bucket at SSE-KMS with a customer-managed key for rotation, separate access policy, and CloudTrail visibility.
  4. Fix the IaC module default and keep the Config rule on so a regression is caught within minutes.

Remediation script · bash

# 1. Audit every bucket and flag the ones still on the default key (SSE-S3).
for b in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do
  alg=$(aws s3api get-bucket-encryption --bucket "$b" \
    --query 'ServerSideEncryptionConfiguration.Rules[0].ApplyServerSideEncryptionByDefault.SSEAlgorithm' \
    --output text 2>/dev/null)
  [ "$alg" != "aws:kms" ] && echo "FAIL S3.17: $b (current: ${alg:-none})"
done

# 2. Flip a bucket to a customer-managed KMS key WITH Bucket Keys (cost lever) enabled.
KEY=arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
aws s3api put-bucket-encryption --bucket customer-records-prod \
  --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"'$KEY'"},"BucketKeyEnabled":true}]}'

# 3. Re-enable encryption on a CodeBuild project's S3 logs (CodeBuild.3).
aws codebuild update-project --name api-service-build \
  --logs-config '{"s3Logs":{"status":"ENABLED","location":"my-build-logs-bucket/api-service","encryptionDisabled":false}}'

# 4. Migrate existing objects in place so the whole dataset sits behind the controlled key.
aws s3 cp s3://customer-records-prod/ s3://customer-records-prod/ \
  --recursive --sse aws:kms --sse-kms-key-id $KEY

Full walkthrough (console steps, edge cases and verification) in the lesson Encrypt S3 object storage at rest.

Is CodeBuild.3 a false positive?

encryptionDisabled=true overrides the bucket's own default encryption, so a bucket configured with default SSE-S3 still fails the control — the project-level flag wins. The control is only relevant when s3Logs.status is ENABLED; CloudWatch-only projects are out of scope.

Part of the learning path Encrypt everything
  • CodeBuild.1 A CodeBuild Bitbucket URL contains embedded credentials
  • CodeBuild.2 CodeBuild env vars contain clear-text credentials
  • CodeBuild.4 Projects should have a logging configuration
  • CodeBuild.7 Report group exports should be encrypted at rest