How do you scan Docker images for vulnerabilities in a CI pipeline?
Quick Answer
You integrate vulnerability scanners like Trivy, Grype, or Snyk into your CI pipeline to analyze image layers, OS packages, and application dependencies against known CVE databases, then enforce policies that fail the build when critical vulnerabilities are found.
Detailed Answer
Think of image scanning like an airport security checkpoint. Every bag (image layer) goes through an X-ray machine (vulnerability scanner) that compares its contents against a database of known threats (CVE databases). If the scanner finds a prohibited item above a certain threat level, the passenger (image) is stopped from boarding (deploying). Just as airports have different alert levels that determine what gets flagged, your CI pipeline has severity thresholds that control whether a vulnerability blocks deployment or merely generates a warning.
Docker image vulnerability scanning is the process of analyzing every layer of a container image to identify known security vulnerabilities in operating system packages, application dependencies, and configuration issues. Scanners decompose the image into its constituent layers, extract the package manifests — such as dpkg status files for Debian, RPM databases for Red Hat, package-lock.json for Node.js, and requirements.txt for Python — and compare every installed package version against databases like the National Vulnerability Database (NVD), GitHub Advisory Database, and distribution-specific security trackers. Each identified vulnerability is assigned a severity rating (Critical, High, Medium, Low) based on its CVSS score, and the scan report maps these to specific remediation steps such as upgrading a package or switching to a patched base image.
Under the hood, modern scanners like Trivy maintain a local or cached copy of vulnerability databases that are updated with each CI run. When Trivy scans an image, it first pulls and extracts the image manifest and layer blobs, then walks through each layer's filesystem to identify package managers and their installed packages. For OS-level scanning, it reads distribution metadata to determine the exact OS version and matches packages against the corresponding security tracker. For application-level scanning, it parses lockfiles and dependency trees to detect vulnerabilities in transitive dependencies that your code never directly imports. Grype uses a similar approach but with the Anchore vulnerability database. Both tools output machine-readable formats like JSON and SARIF that integrate with CI platforms, code scanning dashboards, and security information and event management systems.
In a production CI pipeline, image scanning should be a mandatory gate before any image is pushed to a container registry. The typical workflow is: build the image, scan it with a severity threshold, fail the pipeline if critical or high vulnerabilities are found, and only then push the tagged image to the registry. Most teams run scans at two points: during the CI build and on a scheduled basis against images already in the registry, because new CVEs are published daily against previously clean packages. Integration with GitHub Actions, GitLab CI, or Jenkins is straightforward — Trivy provides official actions and plugins. Teams also implement allowlists for false positives or vulnerabilities with no available fix, storing these in a .trivyignore or policy file committed alongside the Dockerfile.
A critical gotcha is scanning only the final image and missing vulnerabilities introduced in build stages. If your multi-stage build copies a binary from a builder stage that was compiled against a vulnerable library, the final image scan may not detect it because the vulnerable package exists only in the builder stage. Static analysis tools like Snyk can scan the Dockerfile itself to catch insecure base images and risky RUN instructions. Another common mistake is failing to update the vulnerability database before each scan — stale databases produce false negatives. Always ensure your scanner fetches the latest database as part of the CI step. Finally, remember that scanning is not a substitute for keeping base images updated; schedule regular rebuilds to pull patched base images even when your application code has not changed.