ASVS 5.0 V13.3.1 requires a secrets management solution, such as a key vault, to create, store, control access to and destroy backend secrets: passwords, key material, database and third party integration credentials, seeds for time based tokens and API keys. Secrets must not appear in source code or in build artifacts. It is a Level 2 requirement, and Level 3 applications need a hardware backed solution such as an HSM.
Why it matters
Secrets in repositories are found. They live in git history after deletion, in forks, in CI logs and in container image layers. Public repositories are scanned continuously by automated tools, and private ones leak through compromised accounts. A secrets manager gives you access control, audit logs and a single place to rotate.
How to implement it
- Store secrets in a vault service (cloud secret manager, HashiCorp Vault or similar) and fetch them at runtime with the workload's own identity.
- Keep them out of images and repositories: no .env files committed, no ARG or ENV with secret values in a Dockerfile.
- Scan on every commit and on images before release.
Fetching a secret at startup with AWS Secrets Manager in Python:
import boto3, json
client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="prod/orders/db")
db = json.loads(resp["SecretString"])
# db["username"], db["password"] used to open the pool; never log them
Kubernetes users can mount secrets from an external store through a CSI driver instead of storing them as plain base64 objects, and should enable encryption at rest for the cluster secret store.
Docker build secrets without baking into layers:
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
For Level 3, keep master keys inside an HSM or a cloud KMS that is HSM backed, so key bytes never leave it.
How to test it
- Scan the repository including history, and every container image, for credentials.
- Run
docker history --no-truncon images and inspect layers for secret strings. - Grep build logs for token patterns.
- Check vault audit logs show reads by the expected identity only.
Safeguard offers a free in browser dependency scan at https://gold.safeguard.sh/scan, and the demo below shows how secrets scanning reports a leaked key.
Click through it at your own pace, or open it full screen.
Common mistakes
- Deleting a committed secret without rotating it. History keeps it.
- Passing secrets as command line arguments, visible in process listings.
- Secrets in crash dumps, debug logs or error messages.
- Using the vault but giving every service read access to everything (see V13.3.2).
Try it yourself
Run a history aware secret scan on your most important repository. Count findings, then sort them: live and valuable, expired, or test values. For each live finding, rotate first and clean up second. Next, build your most used container image and inspect its layers for credential strings, and read the last CI log for anything that looks like a token.
Then pick one service and move its credentials into your secrets manager end to end: store the value, grant the service identity read on that one path, change the code to fetch it at startup, delete the old value from the repository and environment files and rerun the scan. One completed service gives you a template to repeat across the rest.
Quick check
We removed the key from the repo in a new commit. Are we done?
No. Treat it as compromised, rotate it, and purge it from history where possible.
What changes at Level 3?
The secrets solution must be hardware backed, for example an HSM.