Repository navigation
feat(s130): the hardened headless image and the evidence about it - #117
Merged
Merged
Conversation
The hardening half of slice 130. Release composition waits on slice 133. One recipe, two artifacts. ci/ironbank/ is laid out as the repo1 project root (Dockerfile, hardening_manifest.yaml, LICENSE, README.md, scripts/entrypoint.sh): OTP built from source with FIPS on UBI9, the release copied onto UBI9 micro, the base through ARG BASE_*, every input a manifest resource with its digest and no network except dnf, UID 10001, Erlang distribution off and no baked cookie. ci/headless/ keeps what belongs to our published image: digest pins, justifications, allowances, STIG dispositions and the submission holds. The Debian Containerfile from slice 061 is removed. Four tasks carry the checks: - trinity.ironbank.lint covers AC2, AC2a, AC6 and AC6a on the tree. - trinity.image.inspect covers AC1 and AC6 on the built image. - trinity.image.findings covers AC3 and AC4, keyed the way Iron Bank's tracker keys a finding. - trinity.image.stig covers AC5 from OpenSCAP's own results. The scanner is grype, chosen by measurement over Trivy: only grype found OTP inside the release. Red evidence R1 to R11 is in the slice NOTES with the logs in proof/. The live image's scan is red on 14 OTP findings, fixed in 28.5.0.7; the toolchain bump is the owner's to approve, so they stay unjustified. Signed-off-by: Ayla Croft <aylacroft@proton.me>
scripts/headless_image.sh build TAG, with no directory, set an EXIT trap that read the function's local `dir`. By exit the local was gone, so under set -u the trap failed with "dir: unbound variable", the script exited 1 after a successful build, and the 453 MB context stayed in /tmp. The headless-image workflow calls it exactly that way, so its image job would have failed on every run. The path is now expanded into the trap when it is set. Found by slice 131 (F-131-2) and reproduced here in isolation before the fix. Signed-off-by: Ayla Croft <aylacroft@proton.me>
Run 37764956008 built the image and then failed two checks, neither in the image:
- `mix trinity.image.inspect` ran `docker save` on the base, which BuildKit keeps in its own
cache and not in the image store ("reference does not exist"). The task now pulls the base
when it is missing. The ref is pinned by digest, so the pull gets the bytes the build used.
- grype's `db update` ran as a non-root user with no writable TMPDIR. The scan run already set
one; the update now sets the same one.
Both were reproduced here first: with the base untagged, `docker save` gives the runner's
error and the task pulls the same image id and passes; the old update command fails with the
runner's "permission denied" and the new one exits 0.
Signed-off-by: Ayla Croft <aylacroft@proton.me>
Signed-off-by: Ayla Croft <aylacroft@proton.me> # Conflicts: # CHANGELOG.md
….6 with a TLS 1.2 clamp Owner decision D2 (2026-10-08). The container images build OTP 28.5.0.7 from source (ci/container.tool-versions; the Iron Bank manifest, the Dockerfile and the FIPS Containerfile read it; the source sha256 matches the release's SHA256.txt). The desktop stays on 28.5.0.6, because Burrito's CDN has no 28.5.0.7 ERTS for Linux or macOS, and holds every outbound TLS client to TLS 1.2 while the loaded ssl carries CVE-2026-89422 (Trinity.TLS: the ssl application default, Req's default Finch pool, ReqLLM's pools). The clamp lifts itself when ssl reaches 11.6.0.6. ADR-0014 records the window; a daily canary opens a pull request when Burrito can fetch the container's OTP for every desktop target. The ironbank lint holds the manifest to the container pin, both pins to one major, and the container pin no older than the desktop's. THIRD_PARTY_LICENSES --check accepts OTP application versions differing, and only on the container's runtime. Built and scanned locally: the image on 28.5.0.7 has 0 of the 14 findings; inspect 0 violations; STIG every rule disposed. Signed-off-by: Ayla Croft <aylacroft@proton.me>
This was referenced Oct 8, 2026
Signed-off-by: Ayla Croft <aylacroft@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 130's hardening half. The slice stays
in_progress: release composition (dropping the neural group, the Hex-tree andcargo vendorresources) waits on slice 133, and AC7 is the owner's submission review.What lands
ci/ironbank/, the repo1 project root:Dockerfile: OTP from source with FIPS on UBI9, the release copied onto UBI9 micro. The base comes throughARG BASE_*, every input is a manifest resource with its digest, there is no network except dnf, it runs as UID 10001, and Erlang distribution is off with no baked cookie.hardening_manifest.yaml,LICENSE,README.md,scripts/entrypoint.sh.ci/headless/: digest pins,justifications.yaml,image_allowances.yaml,stig_dispositions.yamlandsubmission_holds.yaml(three holds, each with an owner, a date and a lift condition). The slice 061 DebianContainerfileis removed, so there is one recipe.trinity.ironbank.lint,trinity.image.inspect,trinity.image.findingsandtrinity.image.stig.scripts/headless_image.shandscripts/stig_scan.sh.headless-imageworkflow: on a path filter, nightly, and by hand.docs/regulated/headless-image.mdandstig-applicability.md.Criteria
USER rootfails--network=noneon every stage but the two dnf ones0777,dnf, and a key added and then deletedExpect the
headless-imageworkflow to be redThe live scan fails on 14 OTP findings, 1 of them Critical (
ssl). All 14 are fixed in OTP 28.5.0.7. Moving the toolchain needs the owner's approval, so they are deliberately left unjustified rather than excused. The workflow is not a required check.Evidence
mix format --check-formattedOK;mix credo --strict --allfound no issues;mix trinity.ironbank.lintOK.1044 passed (20 properties, 1024 tests), 18 excluded,prod_check: PASS, coverage 80.51% against 80.31%.