Container Scanning skill for Codex

Fix the base, not one CVE at a time. This skill scans container images for vulnerable OS packages and app dependencies with Trivy and Grype, generates an SBOM with Syft, and drives fixes to the source with the most impact: the base image. It favors rebasing and distroless or multi-stage builds over one-off patches, tracks unfixable CVEs honestly, and gates CI on fixable High/Critical findings.

  • Security
  • $container-scanning
  • 129 lines
  • 2 files
  • ~1,200 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- container-scanning

Installs to ~/.agents/skills/container-scanning/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $container-scanning, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Scans container images for vulnerable OS packages and app dependencies with Trivy and Grype, generates an SBOM with Syft, and drives the fixes — rebase to a patched base, update packages, use distroless/slim, and gate CI on new fixable CVEs. Use when asked to scan a Docker image, reduce image CVEs, produce an SBOM, or add image scanning to a pipeline. Not for scanning source code (SAST).

Use it when

  • Scanning a container image for vulnerabilities
  • Reducing image CVEs or hardening a Dockerfile base
  • Producing an SBOM or adding image scanning to CI

Use something else when

How to check the result

Rebuild and rescan so fixable High/Critical drops to zero or a documented unfixable remainder, confirm the image shrank, and run smoke tests on the new base.

The mistake it prevents

Patching individual OS packages a base rebase would fix wholesale, or changing to a distroless/alpine base without smoke-testing that the app still runs.

~/.agents/skills/container-scanning/SKILL.md

--- name: container-scanning description: Scans container images for vulnerable OS packages and app dependencies with Trivy and Grype, generates an SBOM with Syft, and drives the fixes —… license: MIT ---

An image scan is useful when it ends in a smaller, patched image and a gate that keeps it that way — not a CVE count you stare at. Most image CVEs come from the base image and OS packages, so the fix with the most impact is usually the base, not individual patches.

Inspect first

  • Read the Dockerfile and AGENTS.md. Note the base image and tag, whether it is pinned by digest, what packages are installed, and whether it is multi-stage.
  • Decide the target: scan a built image (repo:tag), a tarball, or the filesystem. Scanners pull vulnerability databases over the network; Codex’s sandbox may block that — note when a step needs network, and cache the DB where possible.

Scan

trivy is the fast default; grype is a good cross-check (different DB, catches different things).

# Trivy: OS + language deps, fail on fixable High/Critical
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 myapp:latest

# Grype as a second opinion
grype myapp:latest --only-fixed --fail-on high

# Scan the Dockerfile/IaC for misconfig too (Trivy config scanning)
trivy config .

Key flags:

  • --ignore-unfixed / --only-fixed — hide CVEs with no available patch; you cannot fix those by updating, so they are noise in the action list (track them separately).
  • --severity — focus on High/Critical first.
  • --scanners vuln,secret,misconfig (Trivy) — one pass for CVEs, leaked secrets and Dockerfile misconfig.

Triage

For each fixable finding, identify where it lives:

SourceFix
Base image OS packageRebase to a newer/patched base tag; apt-get upgrade in build as a stopgap
App dependency (npm/pip/etc.)Bump it in the lockfile (hand off to dependency-scanning)
Build tool left in final imageUse multi-stage so it never reaches the runtime layer
No fix availableRecord, assess reachability, monitor; do not block CI on it

The biggest wins come from the base image. Prefer, in order: a distroless base (no shell/package manager, minimal surface), a slim/-slim variant, then Alpine (small, but musl can bite some apps — test). Pin the base by digest so a rebuild is reproducible:

FROM gcr.io/distroless/nodejs22-debian12@sha256:<digest>

Shrink the surface (fewer packages = fewer CVEs)

  • Multi-stage build: compile/install in a builder stage, copy only artifacts into a minimal runtime stage. Hand off deep slimming (dive layer analysis, distroless trade-offs) to docker-image-slimming.
  • Do not install curl/bash/build tools in the final stage.
  • Run as a non-root user; drop capabilities (defense in depth, not a CVE fix).

SBOM

Generate a Software Bill of Materials so you can answer “are we affected by CVE-X?” fast without rescanning everything:

syft myapp:latest -o spdx-json > sbom.spdx.json
# Scan an existing SBOM later instead of the image
grype sbom:./sbom.spdx.json

Store the SBOM as a build artifact. For signing/attestation and supply-chain provenance, hand off to supply-chain-security.

CI gate

Fail the build only on fixable CVEs at/above your threshold, so the gate is actionable:

trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 "$IMAGE"

Scan on every image build and on a schedule (new CVEs appear against an unchanged image). Wire the pipeline details via github-actions-workflows; keep DB caching on to stay fast.

Verification

  • Rebuild after fixes and rescan: fixable High/Critical count drops to zero (or to a documented, unfixable remainder).
  • Image size shrank if you rebased/slimmed — confirm with docker images.
  • The app still runs on the new base (distroless/alpine can change runtime assumptions) — run the smoke tests.
  • CI fails on a deliberately outdated base and passes when patched.

Output contract

## Container scan — <image:tag> (<date>)
Base: <image@digest>. Scanners: trivy <ver>, grype <ver>. SBOM: sbom.spdx.json.

### Fixable findings
| CVE | Severity | Package | Installed → Fixed | Source | Action |
|-----|----------|---------|-------------------|--------|--------|
| CVE-2024-xxxx | CRITICAL | openssl | 3.0.11 → 3.0.14 | base OS | rebase to debian12 latest |

### Unfixable (tracked): <list + reachability note>
### Changes: base → <new>, size <old> → <new>. CI gate: fixable HIGH/CRITICAL.

Hard rules

  • Prioritize the base image; patching individual OS packages that a rebase would fix wholesale is busywork.
  • Use --ignore-unfixed for the action list, but still record unfixable CVEs — do not pretend they are gone.
  • Pin the base by digest; a floating tag makes scans non-reproducible.
  • Always smoke-test after a base change; a passing scan on a broken image is not progress.
  • Image scanning is not source SAST — hand off to semgrep-sast for code bugs.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Container Scanning"
  short_description: "Fix the base, not one CVE at a time"
  default_prompt: "$container-scanning Scan this Docker image for CVEs and tell me how to cut them"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem