Files
AutistMask/Makefile
clawbot 9f3cc05985
All checks were successful
check / check (push) Successful in 47s
e2e / e2e-chrome (push) Successful in 1m26s
e2e / e2e-firefox (push) Successful in 44s
fix: verify the build against its own receipt, with the expected mode as an argument (closes #309)
script/verify-build computed its expectation from AUTISTMASK_DEBUG in its own
environment, and the Makefile invoked it bare, so an operator with that flag
exported who ran the release target got a debug bundle -- every wallet it
creates carrying the publicly committed test recovery phrase -- verified green
at exit 0. The mode is now the required argument --expect release|debug, with
no default and nothing read from the environment; make build passes
--expect release on an env -u AUTISTMASK_DEBUG environment and make build-debug
passes --expect debug. The flag is deliberately still allowed to reach the
compiler, so a shell that has it exported fails make build loudly rather than
quietly receiving something other than the release build it asked for.

The other half was provenance. The check was a marker grep over a file list
read back out of dist/, so a 26-byte file containing only
autistmask-build-debug=off verified ok, manifest.json and the content script
that runs on every page were never read at all, and an entire hand-written
dist/ passed as "1 bundle(s) verified".

build.js now records every file it emits and writes a receipt of them -- path,
sha256, and whether the file is one of the bundles containing constants.js --
to a path the Makefile creates with mktemp per invocation, outside the repo,
and deletes afterwards; a receipt path inside dist/ is refused. dist/ is
cleared before a build, so it holds only what that build wrote.
dist/constants-bundles.txt is gone, and with it the standalone make verify-build
target: re-verifying a dist/ out of the dist/ itself is the thing that was
broken.

verify-build now checks the receipt's shape, then that dist/ contains nothing
the build did not emit and no symlinks, then each recorded file's bytes against
its digest and each audited bundle's marker against --expect. The guarantee is
narrow and README.md states it as such: dist/ is byte for byte the output of
the build.js run that just finished. It proves nothing about the honesty of the
source tree or of build.js, and offers nothing to a third party holding a
dist/. That is signing:
#310

script/test-verify-build goes from 18 cases to 39, extended in place: one per
demonstrated bypass, the missing/invalid argument cases, an AUTISTMASK_DEBUG=1
environment that the verifier must ignore, debug bundles that must fail
--expect release, and four checks that read the make build and make build-debug
recipes back out of make -n. The existing failure modes (grep exit-2, find's
status, newline and trailing-space paths, symlinked dist/, and the root probe
that refuses to count permission cases vacuously) are kept.

Verified: make check green (39 suites / 811 tests, 39 verify-build cases,
permission cases enabled), and green again inside the pinned image via
script/cibuild with --no-cache-filter=check, where the harness runs as root and
reports the setpriv runner rather than skipping. Non-vacuity proved by
mutation: disabling the digest comparison fails exactly the four bypass cases,
removing the dist/ walk fails the eight extra-file and symlink cases, restoring
the ambient AUTISTMASK_DEBUG fallback fails the no---expect case, breaking the
Makefile recipe fails the wiring cases, and dropping manifest.json from the
recorded emissions fails a real make build.
2026-08-20 12:11:04 +00:00

3.1 KiB