Skip to content

feat(osv): container image + reusable image test harness (#596)#604

Open
TomHennen wants to merge 2 commits into
mainfrom
feat/596-osv-container-image
Open

feat(osv): container image + reusable image test harness (#596)#604
TomHennen wants to merge 2 commits into
mainfrom
feat/596-osv-container-image

Conversation

@TomHennen

@TomHennen TomHennen commented Jun 24, 2026

Copy link
Copy Markdown
Owner

What

First implementation slice of #596 (depends on the design in #603). Containerizes osv and lands a reusable image test harness. Ready for review — what is here is validated + green; the two decisions below gate the next steps (publish + PR2), not this PR.

Validated locally (evidence)

The key de-risking result: the image reuses the existing tools/osv/adapter.sh + render_md.sh + lib/sanitize.sh verbatim as its entrypoint, so a containerized run is byte-identical to today's adapter — no new adapter logic.

clean source        -> exit 0, valid empty SARIF
vulnerable go.mod    -> exit 1, 2 findings, osv markdown (CVE-2021-3121, HIGH, fixed version)
-u 4242:4242 (arb.)  -> works (HOME=/tmp), output owned by the caller UID

The harness self-test is 5/5 green, and shellcheck + wrangle-shell-lint pass.

In this PR

  • tools/osv/Dockerfile — multi-stage: builds osv-scanner from the pinned tools/go.mod (manifest-preserving — keeps Dependabot/osv/govulncheck visibility; not a git-clone-rebuild), then runs the existing adapter as the contract entrypoint on a digest-pinned distroless-ish base.
  • test/lib/image_test_harness.bash — reusable: run any tool image under the contract sandbox (--network, -u, /src:ro, /output) and assert exit code + SARIF validity + write confinement.
  • test/fixtures/image-contract/ — a mock conforming image driving each contract path so the harness self-validates (a mock is justified here: a real tool can't emit a controlled exit-2 / malformed SARIF on demand).
  • test/image/test_image_harness.bats — the harness self-test. Placed outside the Makefile's unit bats glob (it needs docker, absent in the unit test container); the dogfooded shell build auto-detects it on a docker-capable runner.

Open decisions for your review

  1. Publish wiring. build_and_publish_container sets context: {{defaultContext}}:<path>, i.e. the build context is the path subdir. A wrangle tool image's build needs repo-root files (tools/go.mod, lib/sanitize.sh), which a subdir context can't reach. Options: (a) add a context/dockerfile input to build/actions/container so the Dockerfile and context can differ (touches the L3 build path — your call), or (b) a dedicated tool-image build workflow. I did not change the L3 path unsupervised.

  2. Where/how tool-image tests build + run in CI. The osv image test builds osv-from-source (~GB of modules) — heavy enough that running it inside the shell build's every-.bats pass risks disk/time blowups (it filled my local disk). The lightweight harness self-test runs green now; the osv image test is written and locally validated but held pending an image build/cache strategy for CI (e.g. build-and-cache the image once, then point tests at the tag).

Follow-ups

  • PR2 (run.sh docker run seam) is stacked on this and bootstrap-blocked until the osv image is actually published (decision 1).
  • The osv image test (tools/osv/test_image.bats) is ready to add once decision 2 lands.

🤖 Generated with Claude Code

First slice of the tool-containerization work. Adds:

- tools/osv/Dockerfile — builds osv-scanner from the pinned tools/go.mod
  (manifest-preserving; not a git-rebuild) and reuses the existing
  tools/osv/adapter.sh + render_md.sh as the contract entrypoint, so a
  containerized run produces byte-identical output to today's adapter.
  Validated locally: clean source -> exit 0 + empty SARIF; vulnerable go.mod
  -> exit 1 + findings + the osv markdown summary; runs under an arbitrary
  -u UID (HOME=/tmp).
- test/lib/image_test_harness.bash — reusable helpers to run any tool image
  under the contract sandbox (read-only src, /output-only, arbitrary UID) and
  assert exit code + SARIF validity + write confinement.
- test/fixtures/image-contract/ — a mock conforming image driving each
  contract path (clean/findings/error/malformed) so the harness self-validates.
- test/image/test_image_harness.bats — the harness self-test. Lives outside the
  Makefile unit glob (needs docker); the dogfooded shell build auto-detects it.

Draft: the publish wiring and the (heavier) osv image test depend on two
owner decisions noted in the PR description.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wrangle-shell-lint requires 'set -euo pipefail' as the first substantive line,
which needs bash; switch the mock entrypoint to #!/bin/bash and its base from
alpine to debian-slim (bash available). Harness self-test stays 5/5 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TomHennen TomHennen marked this pull request as ready for review June 24, 2026 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant