# Deciding: Fix the Dockerfile, or Add an Exception?

For each blocking (or near-expiry non-blocking) finding, work out which package introduced it and how, then default to fixing it — an exception is a fallback for when a fix genuinely isn't available or is disproportionately risky right now, not a first resort.

## Step 1 — Find the Dockerfile

Locate the user's local copy of the `theorchard/docker-parent-images` repo. The directory name matches the finding's image tag and the `LABEL parent-images=<name>` inside the Dockerfile.

## Step 2 — Work out how the vulnerable package gets into the image

The `Installed Version` column tells you the package (e.g. `pkg:pypi/pip@25.0.1`, `pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.16.0`). Check the Dockerfile to see whether that package is:

**(a) Installed directly** by a `RUN pip install`, `RUN apt-get install`, `RUN npm install`, etc. — the common case for pip/npm packages.

**(b) Bundled inside the `FROM` base image** — common for anything living under a base-image-owned path (e.g. a JAR under `/usr/share/java/...` in a Confluent image, or a library baked into a vendor base like `public.ecr.aws/lambda/...`). You didn't install it; the base image did.

This distinction drives everything below.

## Step 3 — If a fix exists (`Fixed Version` is not `N/A`)

**Case (a), directly installed:** pin the package to the fixed version (or higher) in the Dockerfile, following whatever install step already exists for it. **Before recommending a version, confirm it's actually published** — don't take the scanner's `Fixed Version` on faith, and don't guess a plausible-looking version number:

```bash
# PyPI
curl -s -o /dev/null -w "%{http_code}\n" "https://pypi.org/pypi/<package>/<version>/json"
# npm
curl -s -o /dev/null -w "%{http_code}\n" "https://registry.npmjs.org/<package>/<version>"
# Maven Central (note the jar path, not a JSON API)
curl -s -o /dev/null -w "%{http_code}\n" "https://repo1.maven.org/maven2/<group-path>/<artifact>/<version>/<artifact>-<version>.jar"
```
A `200` confirms it exists. If it 404s, the scanner's fixed-version field may be stale or wrong — say so rather than proceeding on an unverified assumption.

**Case (b), bundled in the base image:** check whether a newer patch-level tag of the *same* base image line exists — that's almost always lower-risk than jumping to a new major/minor line (which changes far more than the one vulnerable package) or manually swapping out just the affected file.

```bash
curl -s "https://hub.docker.com/v2/repositories/<org>/<image>/tags?page_size=100&name=<major.minor>" \
  | python3 -c "import json,sys; [print(r['name'], r['last_updated']) for r in json.load(sys.stdin)['results']]" \
  | sort -V
```

Recommend bumping to the latest tag in the same minor line, but **don't assume it actually fixes the CVE** — a base image maintainer's patch releases don't always touch every bundled library. Say explicitly that this needs to be validated by re-running the scan after the bump, before it's treated as resolved.

**Cross-package version compatibility is a real risk with "just swap the one file" fixes**, and worth calling out explicitly if it comes up: some packages need to stay version-aligned with siblings bundled in the same image (e.g. `jackson-databind` needs to match the `jackson-core`/`jackson-annotations` versions also present) — patching only the flagged file while leaving its siblings on an older version can produce a runtime error that a vulnerability scan won't catch. When you see this risk, prefer the base-image-tag bump over a manual file swap, and say why.

**Precedent matters.** Before proposing a new fix pattern, check whether the Dockerfile (or others nearby) already has an established way of handling exactly this situation — e.g. some Dockerfiles in this repo re-install a specific pip package with a comment like "manual upgrade until the base image is updated to fix docker vulnerability." If that pattern exists, follow it rather than inventing a different approach; consistency across the repo's Dockerfiles matters more than any one of them being marginally more elegant.

## Step 4 — If no fix exists (`Fixed Version` is `N/A`), or the only fix is disproportionate

Recommend an exception. This is also the right call when a fix technically exists but only via something like a major-version migration that needs its own dedicated testing effort — don't bundle an unrelated, riskier change into what should be a quick unblock. Note in your recommendation that the exception should be revisited once the larger fix lands. See `exceptions-config.md` for how to add it.

## Always end with a recommendation, not just a diagnosis

For every blocking finding, state plainly: fix now (with the exact Dockerfile change), fix now but validate first (with what to check before merging), or add an exception (with why a fix isn't appropriate right now). Don't leave the user to infer which path you're suggesting.
