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.
98 lines
3.1 KiB
Makefile
98 lines
3.1 KiB
Makefile
.PHONY: bootstrap setup install test test-e2e test-e2e-firefox lint fmt fmt-check check check-censored docker hooks build build-debug vendor-blocklist clean dev
|
|
|
|
# Standard targets are thin shims; the implementations live in script/
|
|
# per the scripts-to-rule-them-all pattern (see the Entrypoints section
|
|
# of README.md).
|
|
|
|
bootstrap:
|
|
@script/bootstrap
|
|
|
|
setup:
|
|
@script/setup
|
|
|
|
install:
|
|
@yarn install --frozen-lockfile
|
|
|
|
test:
|
|
@script/test
|
|
|
|
# Browser end-to-end suites. Both require docker; neither is part of check.
|
|
test-e2e:
|
|
@script/test-e2e
|
|
|
|
test-e2e-firefox:
|
|
@script/test-e2e-firefox
|
|
|
|
lint:
|
|
@script/lint
|
|
|
|
fmt:
|
|
@script/fmt
|
|
|
|
fmt-check:
|
|
@script/fmt-check
|
|
|
|
check:
|
|
@script/check
|
|
|
|
# Assert that the competitor name appears nowhere but its documented
|
|
# exceptions. Part of check, and re-run against dist/ at the end of a build;
|
|
# separate target for re-running it alone.
|
|
check-censored:
|
|
@script/check-censored
|
|
|
|
docker:
|
|
@script/docker
|
|
|
|
hooks:
|
|
@script/install-precommit
|
|
|
|
# build.js writes a receipt of everything it emitted — every path, its sha256,
|
|
# and whether it is a bundle containing constants.js — and script/verify-build
|
|
# checks dist/ against that. The receipt is made here, fresh per invocation,
|
|
# outside the repo, and deleted again: a standing file inside dist/ would be
|
|
# rewritten by whoever rewrote dist/, which is what made the old check
|
|
# satisfiable by a hand-written tree.
|
|
#
|
|
# The expected mode is an explicit argument and AUTISTMASK_DEBUG is scrubbed
|
|
# from the verifier's environment. The script no longer reads it at all; env -u
|
|
# is here so that stays true of anything it calls. It is deliberately NOT
|
|
# scrubbed from the build itself: with AUTISTMASK_DEBUG=1 exported, this target
|
|
# compiles a debug bundle and then fails on it, loudly, rather than quietly
|
|
# handing back something other than the release build that was asked for.
|
|
build:
|
|
@echo "Building extension..."
|
|
@set -eu; \
|
|
receipt="$$(mktemp "$${TMPDIR:-/tmp}/autistmask-build-receipt.XXXXXX")"; \
|
|
trap 'rm -f "$$receipt"' EXIT INT TERM; \
|
|
AUTISTMASK_BUILD_RECEIPT="$$receipt" yarn run build 2>&1; \
|
|
env -u AUTISTMASK_DEBUG script/verify-build --expect release \
|
|
--receipt "$$receipt"
|
|
@script/check-censored --require-dist
|
|
|
|
# Development-only build: enables the red DEBUG / INSECURE banner and makes
|
|
# the hardcoded test recovery phrase the output of wallet creation. Never
|
|
# distribute the artifacts this produces.
|
|
build-debug:
|
|
@echo "Building extension (DEBUG)..."
|
|
@set -eu; \
|
|
receipt="$$(mktemp "$${TMPDIR:-/tmp}/autistmask-build-receipt.XXXXXX")"; \
|
|
trap 'rm -f "$$receipt"' EXIT INT TERM; \
|
|
AUTISTMASK_DEBUG=1 AUTISTMASK_BUILD_RECEIPT="$$receipt" yarn run build 2>&1; \
|
|
env -u AUTISTMASK_DEBUG script/verify-build --expect debug \
|
|
--receipt "$$receipt"
|
|
@script/check-censored --require-dist
|
|
|
|
# Refresh src/shared/phishingBlocklist.json from its hash-pinned upstream.
|
|
# Run deliberately, land the diff: the extension does no runtime fetching, so
|
|
# the shipped list is as fresh as the last vendoring run that was released.
|
|
vendor-blocklist:
|
|
@script/vendor-blocklist
|
|
|
|
clean:
|
|
@rm -rf dist/
|
|
|
|
dev:
|
|
@echo "Building in watch mode..."
|
|
@yarn run build --watch 2>&1
|