Lab 06 — Containerising Tooling¶
Hands-on lab · ← Back to the module concept
Type: Tool-Build — you ship a reusable, documented tool image others run, not a one-off docker run.
Setup¶
git clone https://github.com/plaintext-security/plaintext-labs
cd plaintext-labs/automation/06-containerising-tooling
make demo # builds the trufflehog image and runs it against data/seed-repo/
make shell # shell inside the built container
make scan DIR=/path/to/repo # run the packaged tool against any local repo
make down # remove the image
data/seed-repo/ is reconstituted from a committed bundle (make seed): a small git repository
seeded with the exact leaked-secret classes that show up in real public-repo leaks — a hardcoded
Stripe key (sk_live_…, Stripe's well-known documentation test value, never a live credential), a
high-entropy hardcoded internal service token, and one clean file as a control. No pre-built image is
provided — the point of the lab is that you build the tool image yourself: the starter Dockerfile
is a placeholder that fails make demo until you write the real one.
Authorization note:
trufflehogscans git history for secrets. Run it only against repositories you own or have explicit written authorization to scan.
Scenario¶
Your team keeps re-installing trufflehog by hand — different Go versions, different binary
versions, "works on my machine" results that don't reproduce in CI. The fix is to ship it once,
as a tool image: any engineer pulls and runs it against a repository without installing Go or
chasing version conflicts, and everyone gets the same result. Your job is to build that image to a
tool standard — clear entrypoint and usage, non-root by default, a pinned and checksum-verified
binary on a pinned minimal base, and a short README so the next person can run it without reading
the Dockerfile.
This is a Tool-Build: the deliverable is a reusable product, judged on whether someone else can build it and run it safely — not just on whether it ran once for you.
Do¶
- [ ] Confirm the starting state. Run
make demo— it fails (the placeholder Dockerfile exits with a clear message). Read it; that's your spec to fill. - [ ] Build the tool image in
Dockerfile: FROM ubuntu:22.04— base pinned, notlatest.- Install only what's needed to fetch the binary (
curl,ca-certificates) and clean/var/lib/apt/listsin the same layer. - Download the
trufflehogbinary from its GitHub releases, version-pinned (v3.88.1), and verify its SHA256 checksum before installing — fail the build if it doesn't match. - Create a non-root user
scannerandUSER scannerbefore the entrypoint. ENTRYPOINT ["/usr/local/bin/trufflehog"]and noCMD— so the image behaves like the command anddocker run image --helpreaches the real tool.- [ ] Prove it works.
make demobuilds andtrufflehogflags the hardcoded key indata/seed-repo/. Thendocker run --rm plaintext/trufflehog:1.0 --help— confirm the tool's own usage prints (the image is a tool, not a black box). - [ ] Run it as a tool against arbitrary input:
make scan DIR=$(pwd)on some repo you own — confirm the mount is read-only (-v …:/scan:ro) so the tool cannot modify what it scans. - [ ] Hold it to the reviewer's bar.
checkov -f Dockerfile— read every finding, fix the HIGH ones (non-root and pinning are the usual hits). - [ ] Prove no secret leaked into a layer:
docker history plaintext/trufflehog:1.0 --no-trunc— confirm nothing sensitive appears (the download URL and the tool binary are not secrets). - [ ] Confirm the kill-switch:
docker stopterminates the container cleanly (the binary handles SIGTERM). - [ ] Write the README (below) so the tool is usable without reading the Dockerfile.
Success criteria — you're done when¶
- [ ]
make demobuilds the image and runstrufflehogcleanly againstdata/seed-repo/. - [ ]
trufflehogcorrectly identifies the hardcoded key in the seed repo. - [ ]
docker run plaintext/trufflehog:1.0 --helpprints the tool's usage (clear entrypoint, no surprising default action). - [ ] The container runs as the non-root
scanneruser (docker run --rm --entrypoint id plaintext/trufflehog:1.0shows a non-zero uid). - [ ]
checkov -f Dockerfileshows no HIGH findings. - [ ] No secret appears in
docker history --no-trunc. - [ ] The base image and the tool version are both pinned, and the binary's checksum is verified in the build.
- [ ] A short
README.mddocuments build + usage; another engineer could run the tool from it alone.
Honor system: these are observable on your own machine — run the commands and check your own work. No grader.
Deliverables¶
The packaged tool, as a build-anyone-can-reproduce:
Dockerfile— the hardened, pinned, non-root, checksum-verified image.Makefile—up/down/reset/demo/shellplus thescantarget.README.md— the tool's usage doc: one-line what-it-is, how to build, how to run (make scan DIR=…and the rawdocker run …line), the version it pins, and the authorization note. This is part of the deliverable, not an afterthought — a tool without a README isn't a tool someone else can run.
Lab artifacts (scan output, the seed repo, any captured findings) stay out of commits.
Automate & own it¶
Required. Make the image genuinely reusable by another person, not just runnable by you:
- Add/confirm the
make scantarget that runs the container againstDIR=/path/to/repo make scan. Have a model draft thedocker run -vline, then verify every part yourself: the mount is read-only (-v "$(DIR):/scan:ro") so the tool can't modify the target, and the args after the image reach the entrypoint correctly. - Write the
README.mdusage doc above. Let a model draft it from your Dockerfile + Makefile, then review every claim against what the image actually does (the pinned version, the entrypoint behaviour, the read-only mount) — a usage doc that lies is worse than none.
Commit the Makefile target and the README alongside the Dockerfile. AI drafts → you review every line → you own the tool.
AI acceleration¶
Ask a model to write the Dockerfile for trufflehog, then run it through the tool checklist: is
the base image pinned? the tool version pinned? a non-root user? is the binary checksum verified
before install, or does it curl | sh? The checksum step is the model's most common omission —
and the supply-chain attack it prevents is not hypothetical: between 2017 and 2018 the docker123321
account published 17 backdoored Docker Hub images (cryptominers + reverse shells) that drew roughly
5 million pulls before removal — the reason you pin and build rather than trust a legit-looking name or
an unverified download. Diff the first draft against your hardened version; that diff is the module's
lesson made concrete.
Connects forward¶
The tool-image pattern here — pinned minimal base, non-root, clear entrypoint, checksum-verified binary — is reused by every later lab that ships a containerised tool. Module 07 builds a multi-container enrichment pipeline directly on these Dockerfile skills, and the CI/CD module operates a pipeline that builds and scans images like this one.
Marketable proof¶
"I package security tools as pinned, non-root, minimal-base images with checksum-verified binaries, a clear entrypoint, and a usage README — so any engineer runs the same version of the tool, safely, without a local install."
Stretch¶
- Rebuild on a
cgr.dev/chainguard/static(or distroless) base using a pre-compiled static binary — compare final image size andcheckovfinding count between the two bases; note the CVE-surface difference in your README. - Add a
make image-scantarget that runstrivy(ordocker scout) against the built image and reports CVEs — your tool image should pass its own kind of scan.
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).