Security scanners tend to become part of the furniture in a CI pipeline. You add one step, it reports vulnerabilities, and after a while its image feels as trustworthy as git or docker. The Trivy compromise is a useful reminder that a security tool is still software delivered through a supply chain, and it runs with whatever access your pipeline gives it.
Docker reported that malicious Trivy images were available from Docker Hub under the 0.69.4, 0.69.5, 0.69.6, and latest tags during an exposure window from March 19 to March 23, 2026. The report says the images could steal CI secrets, cloud credentials, SSH keys, and Docker configuration. Docker identified 0.69.3 as the last known clean release at the time of publication. The incident also involved other distribution channels, so a Docker Hub check alone may not cover every installation method. See Docker's incident guidance for the affected digests and investigation details.
The lesson for a CI owner is practical: ask what the scanner could read, which identity it could use, and what machine it could control if the image itself became hostile.
1. Pin the image by digest
A tag such as aquasec/trivy:0.69.3 is easier to read, but a registry owner can move a tag to different image content. Pinning by digest makes the reference point to specific bytes. Resolve the digest from a trusted release source, verify its provenance or signature when available, and review updates deliberately.
TRIVY_IMAGE='aquasec/trivy@sha256:REPLACE_WITH_VERIFIED_DIGEST'
docker run --rm --cap-drop=ALL \
-v "$PWD:/work:ro" \
"$TRIVY_IMAGE" fs /work
Replace the placeholder with the verified digest for the platform you use. A digest gives repeatability, while provenance helps answer who built the image and from which source. Use both checks where your tooling supports them. Apply the same principle to CI actions and other build tools, since a version tag can move too.
2. Give the job only the access it needs
The scanner usually needs the source tree and permission to publish its report. It rarely needs production cloud credentials, deployment keys, or a token that can write to every repository. Keep scan and deploy jobs separate. Give each job a short-lived identity with the smallest required permissions, and expose secrets only to the step that uses them.
For GitHub Actions, begin with restricted workflow permissions and add only what a particular job requires:
permissions:
contents: read
jobs:
scan:
permissions:
contents: read
env:
TRIVY_IMAGE: aquasec/trivy@sha256:REPLACE_WITH_VERIFIED_DIGEST
steps:
- uses: actions/checkout@FULL_COMMIT_SHA
- name: Scan source
run: docker run --rm -v "$PWD:/work:ro" "$TRIVY_IMAGE" fs /work
Replace FULL_COMMIT_SHA with the reviewed full commit SHA for the action. Configure TRIVY_IMAGE from a trusted, digest-pinned value. If a later job deploys, give that job its own narrowly scoped credentials, ideally through your CI platform's short-lived identity mechanism. Avoid printing secrets, placing them in command-line arguments, or passing them into untrusted pull-request jobs.
3. Keep the Docker socket out of scanner containers
Some container scanning examples mount /var/run/docker.sock so the scanner can inspect local images. That socket grants control of the Docker daemon. On a typical CI runner, daemon control can lead to control of the host and access to data available there.
If a compromised Trivy image ran while the Docker socket was mounted, treat the entire host as suspect. The same caution applies to persistent self-hosted runners: an untrusted job may leave changes behind for later jobs. Prefer scanning an image by registry reference or exporting it for inspection without exposing the host daemon. Use isolated, disposable runners for jobs that process untrusted code.
4. Make response steps explicit
If your environment may have pulled an affected image during the reported window, compare local image and registry-cache digests with Docker's list. Check runner logs, image caches, and CI workflow history. Establish which jobs ran the image and what secrets or identities were available to them.
Revoke and rotate every credential those jobs could access, including registry tokens, cloud keys, SSH keys, and CI secrets. Coordinate revocation so old credentials cannot remain usable while replacements are introduced. Invalidate active sessions where possible. If the Docker socket was mounted, isolate and rebuild the runner from a trusted base rather than trusting cleanup inside the existing host. Review cloud and repository audit logs for unexpected use of exposed credentials.
The Trivy supply chain attack does not mean scanners are unhelpful. It shows why their trust should be bounded. Pin the Docker image digest, verify its origin, scope tokens to one job, and run the scanner without host-level access. Those controls limit the damage when a trusted tool or its distribution channel is compromised.