## TL;DR

Secrets get into layers via COPY of env files or RUN steps that write credentials. Inspect the layers, find where the secret entered, and rebuild with multi-stage builds and build-time secret mounts that never persist to a layer.

## Error

```text
secret in docker image layer: scan failed to flag it
```

## Steps

1. Inspect the image history to see which step could have added the secret. Expected: the suspect layer identified.
2. Scan the image with a tool that examines layers, and also extract and grep the suspect layer's filesystem. Expected: confirmation of presence or absence.
3. Rewrite the Dockerfile: multi-stage build, no secret in any COPY, no credentials in RUN commands. Expected: the secret never lands in a layer.
4. For build-time needs, use the build secret mount mechanism so the value is available during build but not stored. Expected: builds work with no persisted secret.
5. Rebuild, rescan, and replace the old image everywhere, including registries. Expected: clean image in use.

## When to use

- Suspected or confirmed secrets in image layers.
- Hardening Dockerfiles against secret leaks.

## When not to use

- Secrets injected at runtime (check the runtime, not the image).
- Registry credential issues.

## Tool compatibility

- Docker BuildKit; layer inspection tools; multi-stage builds.

## Variant phrasings

### secret baked into docker image

Same remediation.

### docker layer contains credentials

Identical.

## Why it happens

Every Dockerfile instruction creates a layer, and anything written in a layer persists in the image forever, including credentials.

## Edge cases

- Squashing or history rewriting does not remove the secret from existing pushed images; replace the image.
- Build cache can resurrect old layers; build with no cache for the fix.
- Old image tags in registries still carry the secret; delete or overwrite them.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_NcVBVj8mBqNehDxvdtgQeA
