Skip to content
intermediate Phase 5 · Docker Security

Image Scanning & Hardening

Scan images for vulnerabilities and create minimal, hardened images.

1h
0 problems
Topic Progress 0%

Vulnerability Scanning

Vulnerability Scanning

Trivy

Trivy is a comprehensive vulnerability scanner for container images:

# Install Trivy
sudo apt-get install trivy
# or
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin

# Scan image
docker build -t myapp:latest .
trivy image myapp:latest

# Filter by severity
trivy image --severity HIGH,CRITICAL myapp:latest

# Exit code 1 if vulnerabilities found (for CI/CD)
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

# JSON output
trivy image -f json -o results.json myapp:latest

# Scan specific package
trivy image --vuln-type os myapp:latest

Docker Scout

Docker's built-in vulnerability scanner:

# Scan with Docker Scout
docker scout cves myapp:latest

# Compare two images
docker scout compare myapp:v1 myapp:v2

# Get recommendations
docker scout recommendations myapp:latest

# Quick CVE lookup
docker scout cves --only-severity critical,high myapp:latest

Snyk Container

# Install Snyk
npm install -g snyk

# Scan image
snyk container test myapp:latest

# Monitor (track in Snyk dashboard)
snyk container monitor myapp:latest

Grype

# Install Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

# Scan
gype myapp:latest

# Filter by severity
gype --fail-on high myapp:latest

# Output format
gype -o json myapp:latest

Understanding CVE Results

Understanding CVE Results

CVE Severity Levels

Severity CVSS Score Description
Critical 9.0-10.0 Remote code execution, no authentication required
High 7.0-8.9 Significant impact, may require user interaction
Medium 4.0-6.9 Limited impact, requires specific conditions
Low 0.1-3.9 Minimal impact, theoretical risk

Example Output

myapp:latest (debian 12.4)
=================================
Total: 15 (UNKNOWN: 0, LOW: 3, MEDIUM: 8, HIGH: 3, CRITICAL: 1)

libssl3 3.0.11-1~deb12u1 debian:
  High: CVE-2023-5678 - OpenSSL memory use after free
  https://avd.aquasec.com/nvd/cve-2023-5678

openssl 3.0.11-1~deb12u1 debian:
  Critical: CVE-2023-9999 - OpenSSL buffer overflow
  https://avd.aquasec.com/nvd/cve-2023-9999

Remediation Strategies

1. Update base image:

# Before
FROM node:18

# After (newer version with patches)
FROM node:20

2. Update packages in Dockerfile:

RUN apt-get update && \
    apt-get upgrade -y --no-install-recommends && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

3. Use distroless/minimal images:

# Before: Full OS image (~200MB)
FROM node:20

# After: Distroless (~80MB, no shell)
FROM gcr.io/distroless/nodejs20-debian12

# After: Alpine (~50MB)
FROM node:20-alpine

4. Pin specific versions:

# Before: Unpinned, may get vulnerable versions
RUN apt-get install -y curl

# After: Pin specific version
RUN apt-get install -y curl=7.88.1-10+deb12u5

Ignore Unfixable Vulnerabilities

Sometimes vulnerabilities have no fix available. Document and accept the risk:

# Trivy: ignore specific CVEs
cat > .trivyignore <<EOF
CVE-2023-12345
# Reason: Not applicable, no exploit available
EOF

trivy image --ignorefile .trivyignore myapp:latest

Image Signing and Content Trust

Image Signing and Content Trust

Docker Content Trust (DCT)

DCT ensures images are signed by trusted publishers and haven't been tampered with.

# Enable DCT
docker trust inspect myregistry.com/myapp

# Sign image when pushing
docker trust key generate mykey
docker trust signer add --key mykey.pub mysigner myregistry.com/myapp
docker trust sign myregistry.com/myapp:v1

# Only pull signed images
export DOCKER_CONTENT_TRUST=1
docker pull myregistry.com/myapp:v1  # Works if signed
docker pull untrusted/image:latest    # Fails - not signed

Cosign (Keyless Signing)

# Install Cosign
curl -sSfL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/local/bin/cosign

# Sign image
cosign sign myregistry.com/myapp:v1

# Verify
cosign verify myregistry.com/myapp:v1

# Sign with key
cosign sign -key cosign.key myregistry.com/myapp:v1
cosign verify -key cosign.pub myregistry.com/myapp:v1

Image Provenance

# Generate SBOM (Software Bill of Materials)
syft myapp:latest -o spdx-json > sbom.json

# Scan SBOM for vulnerabilities
grype sbom:./sbom.json

# Sign SBOM
cosign attest --predicate sbom.json --type spdxjson myregistry.com/myapp:v1

Best Practices

  1. Enable DCT in production registries
  2. Use Cosign for modern signing workflows
  3. Generate SBOMs for all production images
  4. Scan images before and after signing
  5. Use automated scanning in CI/CD pipelines