Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · SecretsManager

SecretsManager.3: Stale unused secrets linger as a leak risk

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub SecretsManager.3 check?

SecretsManager.3 fails when a secret's LastAccessedDate is older than the configured threshold (default 90 days), flagging credentials that nothing has read in a long time and are usually obsolete.

Why does SecretsManager.3 matter?

Every dormant secret is a credential that exists in plaintext somewhere it shouldn't — a developer's CLI cache, an old CI log, a Lambda environment variable that got rotated but never expunged. Each is a path for an attacker who compromises one identity to laterally reach another. It is also pure waste: storage runs $0.40 per secret per month, so a thousand abandoned secrets is roughly $4,800 a year for nothing.

How do I fix SecretsManager.3?

  1. Review each flagged secret and confirm no live role, Lambda, or job still references it.
  2. Delete the unused secret with a recovery window so it can be restored if you were wrong.
  3. Where a value was retired in favour of a new secret, remove the stale one once nothing reads it.

Remediation script · bash

# Enable rotation on an RDS-backed secret with the AWS-managed Lambda, 30-day cadence.
aws secretsmanager rotate-secret \
  --secret-id prod/payments/db-master \
  --rotation-lambda-arn arn:aws:lambda:eu-west-1:123456789012:function:SecretsManagerRDSPostgreSQLRotationSingleUser \
  --rotation-rules AutomaticallyAfterDays=30

# Schedule deletion of stale secrets behind a recovery window (never force-delete in prod).
NOW=$(date -u +%FT%TZ)
for arn in $(aws secretsmanager list-secrets \
  --query "SecretList[?LastAccessedDate<='$(date -u -d '90 days ago' +%FT%TZ)'].ARN" \
  --output text); do
  aws secretsmanager delete-secret --secret-id "$arn" --recovery-window-in-days 7
done

# Alarm so the next failed rotation pages a human, not the next audit.
aws cloudwatch put-metric-alarm \
  --alarm-name secrets-rotation-failed --namespace AWS/Lambda --metric-name Errors \
  --dimensions Name=FunctionName,Value=RotatePaymentsDbMaster \
  --statistic Sum --period 3600 --evaluation-periods 1 \
  --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:security-oncall

Full walkthrough (console steps, edge cases and verification) in the lesson Manage secrets (rotation and hygiene).

Is SecretsManager.3 a false positive?

A secret read only by a rare batch job or annual process can look stale without being unused. Check CloudTrail for genuine recent reads before deleting, rather than trusting LastAccessedDate alone.

Part of the learning path Lock down access