Skip to content

Security Scanning Footguns

Mistakes that give false confidence, miss real vulnerabilities, or break CI pipelines.


1. Scanning only at build time

You scan images in CI and ship clean. A week later a new CRITICAL CVE is published against a library in your running image. Nobody rescans. You run vulnerable code in production for months.

Fix: Scan continuously. Deploy Trivy Operator in your cluster for weekly runtime scans. Re-scan stored SBOMs when new CVEs drop. Build-time scanning is necessary but not sufficient.

War story: Log4Shell (CVE-2021-44228) was disclosed on December 9, 2021. Every image built before that date was clean at build time and vulnerable in production. Organizations with SBOMs and continuous scanning identified affected services within hours. Those without spent days manually checking hundreds of services.


2. Ignoring unfixed vulnerabilities without tracking them

You add every noisy CVE to .trivyignore to keep CI green. Six months later the file has 40 entries, nobody reviews it, and real vulnerabilities are hidden in the noise.

Fix: Every .trivyignore entry must have a comment explaining why and a tracking ticket. Review the ignore file monthly. Remove entries when fixes become available. Use --ignore-unfixed only for the CI gate, not for reporting.


3. Using latest tag in production images

You deploy myapp:latest. Next week you scan myapp:latest — but it now points to a different build. Your scan results do not match what is running. You cannot reproduce findings or verify fixes.

Fix: Always use immutable tags (git SHA, semver). Scan the exact tag you deploy. Store the SBOM alongside the image artifact.


4. Scanning only OS packages, not application dependencies

Trivy scans OS packages by default, but your Python requirements.txt or Node package-lock.json inside the image also has vulnerabilities. You miss the entire application dependency surface.

Fix: Use trivy image (scans both OS and app deps) rather than trivy rootfs. Verify your scan covers language-specific package managers. Check the scan output for your language ecosystem.


5. No SBOM generation

A zero-day drops on a Tuesday. Management asks which of your 200 services are affected. You have no inventory. You spend 8 hours manually checking Dockerfiles and lock files.

Fix: Generate an SBOM for every image at build time. Store them in a searchable location. When a CVE drops, scan the SBOMs: trivy sbom sbom.json gives you the answer in seconds.


6. Running as root in container images

Your Dockerfile has no USER directive. The container runs as root. A vulnerability in your application now has root privileges inside the container. Container escapes become trivial.

Fix: Always add USER nonroot or USER 1000 in your Dockerfile. Use distroless or Alpine images that default to non-root. Scan for this misconfiguration: trivy config Dockerfile.


7. Trusting severity scores without context

You prioritize a CRITICAL CVE in a library you do not use at runtime (it was pulled in as a transitive build dependency). Meanwhile, a HIGH CVE in your HTTP parser — actually reachable — sits unpatched.

Fix: Prioritize by exploitability and reachability, not just CVSS score. Check if the vulnerable function is actually called. Use VEX (Vulnerability Exploitability eXchange) statements to annotate non-applicable findings.

Gotcha: Trivy's default precise mode prioritizes reducing false positives, which can cause false negatives — it may skip a CVE if the package version cannot be uniquely determined. Use --detection-priority comprehensive for critical audits to trade some noise for fewer missed vulnerabilities.


8. Signing images but not enforcing verification

You set up cosign and sign every image. But you never deploy an admission controller to verify signatures. Unsigned or tampered images deploy just fine. The signing gives false confidence.

Fix: Deploy Kyverno or OPA Gatekeeper with a policy that rejects unsigned images. Test enforcement by trying to deploy an unsigned image. Signing without verification is theater.

Remember: The trust chain: sign with cosign, store signature in the registry, verify with an admission controller. If any link is missing, you have a false sense of security. Test by deploying an unsigned image — if it succeeds, your enforcement is broken.


9. Fat base images with massive attack surface

You use ubuntu:22.04 as your base image because it is familiar. It ships with hundreds of packages you never use — each one a potential vulnerability. Your scan reports are noisy with CVEs in packages your application never touches.

Fix: Use minimal base images: distroless, alpine, or *-slim variants. Fewer packages means fewer vulnerabilities, smaller images, and faster pulls. Compare counts: ubuntu:22.04 has 40+ vulns, distroless has 0-2.


10. No secret scanning in CI

A developer commits an AWS access key in a config file. The vulnerability scanner checks for CVEs but not secrets. The key is in the git history forever. Automated bots find it within hours.

Fix: Add secret scanning to CI with gitleaks or trufflehog. Run gitleaks protect --staged as a pre-commit hook. Scan the full git history periodically: gitleaks detect --source ..