A token as a build argument
Recorded in the image history, where anybody who can pull can read it
ARG NPM_TOKEN RUN npm ci
Move a build-time credential out of ARG and into --mount=type=secret. The value then exists as a file during one RUN and is in no layer and no metadata.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Generate. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
Recorded in the image history, where anybody who can pull can read it
ARG NPM_TOKEN RUN npm ci
In the image config and in the environment of every container from it
ENV API_KEY=REPLACE_ME RUN ./setup.sh
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
The value is recorded in the image metadata and docker history shows it to anybody who can pull the image. Removing the file it wrote changes nothing.
Instead:Use RUN --mount=type=secret and pass it with --secret at build time.
Images already pushed still carry the value in their history. The fix protects future builds only.
Instead:Rotate first, then rebuild. Treat anything already published as leaked.
That file is in the layer, which is exactly what the mount was avoiding.
Instead:Do the work that needs the credential inside the same RUN.
An ARG's value is stored in the image metadata and shown by docker history. An ENV is in the image config and in every container started from it. Neither can be removed by a later instruction.
The common attempt is to write the credential to a file, use it, and rm it in the same RUN. That does remove the file from the layer, and it does nothing about the ARG whose value is in the history. The record is the argument, not the file.
It appears at /run/secrets/ID for the duration of that RUN and nowhere else. Read it into a shell variable inside the same instruction and let it go out of scope. Exporting it, or writing it under the build context, puts it straight back into a layer.
--secret id=x,src=./file reads a file, and --secret id=x,env=VAR reads an environment variable, which is the form CI usually wants because the value is already in the runner's secret store.
Changing the Dockerfile does not change images already pushed. Every tag built while the credential was in the history still carries it, and registry garbage collection does not remove a manifest anybody has pulled. Rotate first, then rebuild.
With DOCKER_BUILDKIT=0 the --mount flag is a syntax error, so the build stops rather than quietly building without the secret. That is much better than a silent partial success.
Whether the credential is real, or where else it has been used. It reads the text you paste, in your browser, and never echoes a value it identified as a secret.