Container images often ship with vulnerabilities that can lead to production breaches, compliance failures, or incident response headaches. You need to catch these issues before they hit your cluster. In this post, you’ll see how to use Trivy, Grype, and Snyk—three leading open-source and commercial tools—for automated container image security scanning. We’ll cover how they differ, how to integrate them into CI/CD, and how to interpret their results for real-world workflows.
Key Takeaways:
- Understand why container image scanning is critical for production security
- See concrete, production-ready scanning workflows using Trivy, Grype, and Snyk
- Learn the differences in vulnerability coverage, workflow integration, and output formats
- Spot real-world mistakes teams make when adopting container scanning
- Get actionable advice for securing your CI/CD pipelines and registries
Why Scan Containers?
Container images bundle OS packages, application dependencies, and sometimes sensitive secrets. Vulnerabilities in these layers can give attackers a foothold in your environment. Scanning images before they’re deployed helps you:
- Meet compliance (PCI-DSS, SOC2, etc.) by proving images are checked for CVEs
- Block deployments of known-vulnerable software versions
- Reduce incident response time by shifting security left in your pipeline
Vulnerabilities can lurk in:
- Base OS packages (
libc,openssl, etc.) - Language-specific packages (npm, pip, gem, etc.)
- Embedded secrets or credentials in ENV variables and files
Manual review is impossible at scale. Automated scanners catch these issues early, and provide machine-readable output for audits and policy enforcement.
Trivy Usage Examples
Trivy is a fast, open-source, easy-to-integrate vulnerability scanner. It covers OS packages, application dependencies, IaC misconfigurations, and secrets—all in one tool. Here’s how to use it for production workloads.
Installation
Official installation methods are listed on the Trivy GitHub page. The preferred method for CI/CD and local use is the static binary:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/binAlternatively, use Docker for ephemeral scans:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:latest image nginx:1.23-alpineBasic Image Scan
trivy image --severity CRITICAL,HIGH nginx:1.23-alpineThis command scans the nginx:1.23-alpine image and shows only HIGH and CRITICAL vulnerabilities. The output includes:
- CVE ID, package, installed version, fixed version
- Links to CVE details and descriptions
CI/CD Integration Example
To fail builds on new vulnerabilities, use Trivy with the --exit-code flag:
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latestAdd this to your GitHub Actions workflow:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Scan Docker image with Trivy
uses: aquasecurity/[email protected]
with:
image-ref: 'myorg/myapp:latest'
severity: 'HIGH,CRITICAL'
exit-code: '1'
Scanning for Secrets and IaC Issues
trivy fs --scanners secret,config ./deploy/helm/This scans your deployment manifests for exposed secrets and insecure Kubernetes settings.
Output Formats
Trivy supports JSON, SARIF, template, and table outputs for integration with dashboards and ticketing systems:
trivy image --format json -o trivy-report.json myapp:latestSecurity Hardening
- Always pin Trivy to a known version in CI/CD to prevent breaking changes
- Do not use
--ignore-unfixedunless you have a plan for patching later
Grype Usage Examples
Grype is another open-source vulnerability scanner from Anchore. It focuses on deep, accurate vulnerability matching, especially for SBOM-based workflows.
Installation
Official instructions: Grype Installation
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/binFor Docker-based scanning:
docker run --rm anchore/grype ubuntu:22.04Basic Image Scan
grype nginx:1.23-alpine --only-fixedThis scans for vulnerabilities that have a known fix. You get a table with CVE IDs, severity, package, version, and fix version.
SBOM Workflows
Grype can scan from a Software Bill of Materials (SBOM) directly, which is powerful in regulated environments:
syft nginx:1.23-alpine -o cyclonedx-json > sbom.json
grype sbom:sbom.jsonThis separates inventory (SBOM generation with Syft) from vulnerability scanning (Grype), which is useful for supply chain audits.
CI/CD Integration Example
To fail a pipeline on vulnerabilities above a severity threshold:
grype myapp:latest --fail-on highFor GitLab CI:
scan:
image: anchore/grype:latest
script:
- grype myorg/myapp:latest --fail-on high
Output Formats
Grype supports table, JSON, CycloneDX, and GitHub SARIF outputs for integration with other tools:
grype nginx:1.23-alpine -o json > grype-report.jsonSecurity Hardening
- Run Grype in a clean environment to avoid leaking credentials in build logs
- Pin to a specific version in CI/CD to avoid breaking changes
Snyk Usage Examples
Snyk offers a commercial SaaS platform and CLI for vulnerability scanning. It has a generous free tier and strong language support, but requires an account for most features.
Installation and Authentication
Install via npm or Homebrew:
npm install -g snyk
# or
brew install snyk/tap/snykAuthenticate with your Snyk account:
snyk authBasic Image Scan
snyk container test nginx:1.23-alpine --severity-threshold=highThis checks for HIGH and CRITICAL vulnerabilities in the nginx:1.23-alpine image. You get remediation advice (upgrade, patch, ignore) in the output.
CI/CD Integration Example
To block merges on new vulnerabilities, add this to your GitHub Actions workflow:
jobs:
snyk_scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Snyk Container Scan
uses: snyk/actions/docker@v3
with:
image: myorg/myapp:latest
args: --severity-threshold=high
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Output Formats
Snyk can output JSON for dashboards or reporting:
snyk container test myapp:latest --json > snyk-report.jsonSecurity Hardening
- Never expose your SNYK_TOKEN in logs or public repositories
- Review Snyk’s privacy policy before uploading images to their service
Comparison Table: Trivy vs Grype vs Snyk
| Feature | Trivy | Grype | Snyk |
|---|---|---|---|
| License | Apache 2.0 (Open Source) | Apache 2.0 (Open Source) | Commercial (Free tier) |
| OS Package CVEs | Yes (Broad support) | Yes (Deep match accuracy) | Yes |
| App Dependency CVEs | Yes (npm, pip, gem, etc.) | Partial (improving) | Yes (strong language support) |
| Secrets/IaC Scan | Yes | No | Partial (separate tools) |
| SBOM Support | Yes (input/output) | Yes (best with Syft) | Limited |
| Commercial Support | Optional (Aqua Security) | Optional (Anchore) | Required for advanced |
| Air-gapped Mode | Yes (offline DB updates) | Yes | No |
| Integration | GitHub Actions, GitLab, Jenkins | GitHub Actions, GitLab | All major CI/CD |
Common Pitfalls and Pro Tips
Pitfall: Ignoring Image Updates
Scanning only at release time leaves you blind to new CVEs in static images. Always scan:
- On pull request or merge (CI/CD)
- On schedule (nightly/weekly cron) against images in your registry
Even “stable” base images are updated frequently for new vulnerabilities. Use image digests, not tags, to ensure reproducibility.
Pitfall: Excluding “Unfixable” Vulnerabilities
Flags like --ignore-unfixed can hide real risk. Document why you’re ignoring issues and review regularly. Many “unfixed” CVEs get patches later.
Pitfall: Overriding Exit Codes in CI
Don’t force exit 0 in your pipelines. This leads to alert fatigue and ignored findings. Triage and prioritize issues instead.
Pitfall: Leaking Secrets in Scans
Scanners may output environment variables or secrets. Mask sensitive data in logs and rotate credentials if exposure is detected.
Pro Tip: Use SBOMs for Audit Trails
Generate SBOMs (Software Bill of Materials) and archive them. This helps with forensics and compliance if you need to prove what was deployed and when.
Pro Tip: Automate Patch Recommendations
Snyk and Trivy can suggest package upgrades. Use these outputs to auto-create Jira tickets or PRs for base image updates.
Pro Tip: Combine Multiple Scanners
No single tool is perfect. Run at least two scanners (e.g., Trivy and Grype) for broader coverage and to catch database discrepancies.
Troubleshooting: Common Errors
- “Database update failed”: Your scanner can’t reach CVE feeds. Mirror databases internally for air-gapped environments (Trivy DB).
- “Unauthorized image pull”: Make sure your scanner has Docker registry credentials (use
docker loginor image pull secrets in CI). - “No vulnerabilities found”: Check if you’re scanning an empty/minimal image or if the scanner’s database is up to date.
Conclusion and Next Steps
Integrating container image scanning into your CI/CD and registry workflows is essential for production-grade security. Trivy, Grype, and Snyk each offer unique strengths—choose the right tool or combination based on your compliance needs, language stack, and pipeline architecture.
Next, automate recurring scans, extend coverage to IaC and secrets, and connect findings to your ticketing system for continuous improvement. For more details, see Trivy, Grype, and Snyk Container Documentation. Consider pairing these scanners with runtime security and image signing for defense-in-depth.



