dhacker / PR review console
Dockerfile + Kubernetes manifest review lab. Fake data only.
127.0.0.1 only

PR #214: "Containerise the payments API and deploy it"

Author's description: "Adds a Dockerfile and a Deployment so we can ship the API. Image builds, pods start, tests pass. Cleaned up the secrets after the build. Needs host access for metrics, so I made it privileged."

Your job as reviewer: read both files below and write down every security problem, ranked by impact. Then press Reveal ranked findings to compare with the answer key.

Dockerfile

loading…

k8s/deployment.yaml

loading…

Mission 1: find the key that "was deleted"

The PR author ran rm -f /app/.env /app/.build-token at the end of the Dockerfile. Pick the vulnerable image, type the fake key fake-demo-key-123 in the search box and press Scan layers. Click the highlighted rows to see which file in which layer still holds it. Then press Show what docker run sees: .env and .build-token are gone from the merged filesystem, yet the layers still hold them. Finally switch to fixed and scan again.

Image
Search layers for fake-demo-key-123

Image history (oldest first):

#Instruction (docker history)LayerSizeHits

Rows from the base image are dimmed. "metadata" rows (ARG, ENV, EXPOSE, CMD…) create no layer, but they still appear in the history.

Layer contents

Click a row on the left to list the files that layer added or deleted.
Option 2: from the terminal
docker history --no-trunc dhacker-pr-review/api-vulnerable:lab | grep fake-demo-key-123

docker save dhacker-pr-review/api-vulnerable:lab -o vuln.tar
mkdir vuln && tar -xf vuln.tar -C vuln && cd vuln
# every layer is a tar file: which ones contain the key?
for l in blobs/sha256/*; do tar -xOf "$l" 2>/dev/null | grep -aq fake-demo-key-123 && echo "key in $l"; done
# layers in order (oldest first), then look for .env and its deletion marker
python3 -c "import json;print('\n'.join(json.load(open('manifest.json'))[0]['Layers']))"
tar -tf blobs/sha256/<layer> | grep -E 'app/(\.env|\.build-token|\.wh\.)'
tar -xOf blobs/sha256/<layer-with-.env> app/.env

# what the running container sees:
docker run --rm dhacker-pr-review/api-vulnerable:lab cat /app/.env    # No such file

Mission 2: turn review opinions into rules

Choose a manifest and a Pod Security Standards level, then press Run policy check. Each control from the Kubernetes docs is listed with PASS or FAIL and the exact field that caused it. Start with vulnerable at restricted; then switch the level to baseline and see which failures disappear. Finally run fixed.

Manifest
Level
Namespace mode

Pod Security Standards controls

Field paths are shown relative to spec.template.spec (the pod spec inside the Deployment).

ResultProfileControlField that caused it

Manifest (offending lines marked)

Run the check to see the manifest.

Beyond PSS: reviewer checks the standard does not cover

Run the check.
Option 2: from the terminal
# offline schema validation (needs internet once, to fetch the Kubernetes JSON schemas)
docker run --rm -v "$PWD:/w" -w /w ghcr.io/yannh/kubeconform:v0.8.0 -summary -strict vulnerable/k8s/deployment.yaml

# the same rules as Rego, evaluated by Conftest (offline)
docker run --rm -v "$PWD:/w" -w /w openpolicyagent/conftest:v0.71.1 test \
  --policy policy -n pss.baseline -n pss.restricted vulnerable/k8s/deployment.yaml

# the Python checker the console uses (needs: pip install pyyaml)
python3 policy/pss_check.py vulnerable/k8s/deployment.yaml --level restricted
curl -s "http://127.0.0.1:8090/api/check?target=vulnerable&level=restricted&mode=enforce"

Mission 3: compare vulnerable and fixed

Pick a file. Left is the PR as submitted, right is the fixed version. Amber lines are removed or changed, cyan lines are new. The scoreboard below is computed from the same data as Missions 1 and 2.

File

vulnerable PR as submitted

fixed after review

Scoreboard

Checkvulnerablefixed
Option 2: from the terminal
diff -u vulnerable/Dockerfile fixed/Dockerfile
diff -u vulnerable/k8s/deployment.yaml fixed/k8s/deployment.yaml
python3 policy/pss_check.py vulnerable/k8s/deployment.yaml; python3 policy/pss_check.py fixed/k8s/deployment.yaml
docker run --rm dhacker-pr-review/api-vulnerable:lab id    # uid=0(root)
docker run --rm dhacker-pr-review/api-fixed:lab id         # uid=10001 gid=10001