Skip to content

Manual Test Runbook — I1: Container Image Scanning

Owner: Sagar  |  Time: ~3 min (Part A offline) · +10 min (Part B live scan)  |  Cloud: none · $0

Promotes I1 (.github/workflows/image-scan.yml) from 🟦 Code Complete → 🟩 Shipped. Reusable workflow_call image scan (Trivy). Distinct from C2's build-time grype: I1 scans an arbitrary image ref (base image, vendor image, periodic re-scan). Part A is offline (YAML lint). Part B is a live scan via workflow_dispatch.


Prerequisites

  • Local tooling: python3 (YAML lint), optionally docker + trivy for a local dry-run
  • (Part B only) gh authenticated; the workflow present on the default branch
  • Working directory: repo root

Steps

Part A — workflow lint (offline, ~3 min)

  1. bash python3 -c "import yaml; yaml.safe_load(open('.github/workflows/image-scan.yml')); print('parses OK')" # Optional, if installed: actionlint .github/workflows/image-scan.yml

Expected: parses OK. Confirm workflow_call inputs (image, severity_cutoff default CRITICAL,HIGH, ignore_unfixed, fail_on_findings, upload_sarif) and optional registry_username / registry_password secrets.

  1. (Optional) local equivalent of the gate, no CI needed:
trivy image --severity CRITICAL,HIGH --ignore-unfixed --exit-code 1 alpine:3.14

Expected: a known-old base image (alpine:3.14) fails (exit 1); a current alpine:latest passes (exit 0). Proves the cutoff/exit-code wiring.

Part B — live dispatch scan (~10 min, $0)

  1. Run the scan against a deliberately-old image:
gh workflow run image-scan.yml -f image=alpine:3.14

Confirm the trivy (image) job fails on High/Critical findings and the results appear under Security → Code scanning (category trivy-image).

  1. Re-run with a clean current image (-f image=alpine:latest) and confirm green.

  2. (Optional) Wire a real caller: a downstream repo's workflow uses: this file with image: <acr>.azurecr.io/app@sha256:... and registry secrets; confirm the optional registry-login step runs only when a username is supplied.


Sign-Off

Field Value
Part A (lint) ☐ PASS
Part B (live scan) ☐ PASS / ☐ skipped
Tester
Date
Result ☐ PASS