AUR-359 — Fixar trust root do runner OCI
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
Purpose
Pins the trust root of the OCI runner used by the board's temporary shell
bootstrap: the exact digest of the pinned base image, the exact digest of
.board/bin/oci-run itself, and the hardened container flags every future
consumer of the trust-root-docker-v1 profile must reproduce byte-for-byte.
tests/acceptance/AUR-359.sh verifies all four artifacts independently of
.board/bin/oci-run — the card's own accept line runs a direct,
digest-pinned docker run, never the wrapper it authorizes.
Artifacts and schema
.board/bootstrap/locks/trust-root.yml
Flat key: value document, LC_ALL=C, one pair per line, 0 < size <= 4096
bytes. Exactly these 12 keys, each declared once:
| Key | Value |
|---|---|
schema |
bootstrap-lock-v1 |
card |
AUR-359 |
runner_script |
.board/bin/oci-run |
runner_script_sha256 |
sha256:<64 hex> — recomputed SHA-256 of .board/bin/oci-run |
runner_image |
bash@sha256:ae4668c2560999e65e89532cd2ad1b6688bb23298189f0bd229ef80fa4bd0831 |
profile_user |
65532:65532 |
profile_network |
none |
profile_read_only_rootfs |
true |
profile_cap_drop |
ALL |
profile_no_new_privileges |
true |
engine_docker |
observed — Docker 29.6.1 was observed in this workspace |
engine_podman |
not-observed — Podman is not installed; no Podman verdict is emitted |
.board/oci/profiles/trust-root-docker-v1.json
Flat JSON container profile using the same 24-key schema
.board/bin/oci-run's own resolve_profile requires of any registered
profile (schema, version, profile, lock, lock_digest, network,
user, cap_drop, cap_add, mounts, devices, pull, tmpfs,
read_only_rootfs, no_new_privileges, privileged, timeout_seconds,
memory_mb, cpu_millis, pids_limit, tmpfs_mb, stdout_limit_bytes,
stderr_limit_bytes, max_input_files, max_input_bytes). Its hardening
fields are identical to the flags in the card's accept vector:
network=none, user=65532:65532, cap_drop=ALL, read_only_rootfs=true,
no_new_privileges=true, privileged=false, memory_mb=128,
cpu_millis=500 (--cpus=0.5), pids_limit=64. lock points at the file
below by its repository-relative path; lock_digest is the recomputed
SHA-256 of that file's content, never a value trusted from the file itself.
.board/locks/oci/trust-root-docker-v1.lock.json
Flat JSON image lock: schema (aurum.oci-image-lock), version (1),
profile (trust-root-docker-v1), image
(bash@sha256:ae4668c2560999e65e89532cd2ad1b6688bb23298189f0bd229ef80fa4bd0831).
image must match ^[a-z0-9][a-z0-9._/-]*@sha256:[0-9a-f]{64}$ — a bare tag
or a mutable reference (bash:latest) is refused before any other check.
Both JSON documents are registered exactly as .board/bin/oci-run expects,
so a future card that runs ./.board/bin/oci-run --profile
trust-root-docker-v1 --card <id> resolves the same profile this card seals
— but this card's own accept never depends on that wrapper, which is the
point: fixing the trust root cannot depend on the thing it authorizes.
Bounds
| Bound | Value |
|---|---|
| Lock/profile/oci-lock document size | 4096 bytes |
tests/bootstrap/locks/AUR-359/cases.tsv size |
4 MiB |
cases.tsv rows |
256 |
Acceptance container wall-clock (accept vector, informational) |
15 s |
Codes
Typed dispositions this card's acceptance program can emit on stderr as
AUR-359/AC-001/<code> (exit 1, behavioral) or
AUR-359/AC-001/inconclusive/<reason> (exit 79, environment):
| Code | Trigger |
|---|---|
trust_root_mismatch |
An owned artifact (lock, runner, profile, or oci lock) is absent, or a checked value diverges from the pinned trust root. |
source_integrity_error |
An owned artifact is a symlink, or otherwise not a plain regular file. |
invalid_lock_or_manifest |
An owned document is empty, malformed, missing a required field, or its declared lock_digest diverges from the recomputed content digest of the file it binds to. |
input_limit_exceeded |
An owned document exceeds 4096 bytes. |
runner_missing |
.board/bin/oci-run is absent (a trust_root_mismatch specialization, named separately because it identifies which artifact is missing). |
runner-digest-mismatch |
The lock's runner_script_sha256 diverges from the recomputed SHA-256 of .board/bin/oci-run (MUT-001). |
image_digest_mismatch |
The lock does not contain the pinned bash@sha256:... reference. |
egress-guard-missing |
profile_network/network is not none, or read_only_rootfs is not true (MUT-002). |
mutable-image |
The oci lock's image is not pinned by an immutable digest (MUT-003). |
mutable_reference |
The trust-root lock itself contains a latest/branch-style reference. |
fixture_sensitivity_error |
This program's own fixture self-test (cases.tsv) observed a disposition other than what the sealed row declares — the verifier failed to discriminate a known mutant. |
Diagnostic example (synthetic)
$ ./.board/bin/oci-run --profile trust-root-docker-v1 --card AUR-999 # illustrative only
oci-run: profile trust-root-docker-v1 declares network as none, cap_drop as ALL, ...
$ docker run --rm --network=none --read-only --cap-drop=ALL \
--security-opt=no-new-privileges --pids-limit=64 --memory=128m --cpus=0.5 \
--user=65532:65532 -v "$PWD":/src:ro \
bash@sha256:ae4668c2560999e65e89532cd2ad1b6688bb23298189f0bd229ef80fa4bd0831 \
/src/tests/acceptance/AUR-359.sh
{"card":"AUR-359","scenario":"AC-001","selector":"AC-001","fixture_cases":5,"result":"pass"}
An absent lock instead produces, on stderr, exit 1:
AUR-359/AC-001/trust_root_mismatch
AUR-359/AC-001/detail expected-artifact=.board/bootstrap/locks/trust-root.yml
Offline OCI command
This is exactly the card's accept: line — a direct, digest-pinned
docker run, reproducible offline once the bash@sha256:... image is
present in the local image cache (no registry pull is attempted; the profile
declares "pull": "never"):
docker run --rm --network=none --read-only --cap-drop=ALL \
--security-opt=no-new-privileges --pids-limit=64 --memory=128m --cpus=0.5 \
--user=65532:65532 -v "${PWD}":/src:ro \
bash@sha256:ae4668c2560999e65e89532cd2ad1b6688bb23298189f0bd229ef80fa4bd0831 \
/src/tests/acceptance/AUR-359.sh
Why the accept vector bypasses .board/bin/oci-run
.board/bin/oci-run resolves a profile's image digest from
.board/locks/oci/<name>.lock.json — the very file this card produces. A
card that fixes the trust root cannot prove that root by first trusting the
wrapper the root is meant to authorize; a bug in oci-run's own
resolve_profile could otherwise mask a divergence in the thing under test.
The accept line therefore invokes Docker directly with the identical
hardened flags the trust-root-docker-v1 profile declares, and
tests/acceptance/AUR-359.sh re-implements the profile/lock parsing
independently rather than sourcing or exec'ing oci-run.