The blocklist URL in shipped code named a competitor and pointed at a moving ref, and the extension re-fetched from it every 24 hours, which also meant a third party decided what this wallet warns about. All of that is gone. script/vendor-blocklist fetches upstream at a pinned commit, verifies the sha256 of the bytes that commit serves, and writes src/shared/phishingBlocklist.json. It is build-time tooling, never shipped, and the one place in the repo that names the upstream project; a source reference nobody can verify is not a source reference. The artifact stores truncated sha256 digests rather than domain names. That is what censors it: the previous file contained the competitor's name 6,475 times, as phishing domains impersonating them, and not one of those domains is dropped. It also makes lookups a binary search over a fixed-width string, so nothing is built at module load — which matters on MV3, where the worker re-evaluates the module on every wake — and takes the file from 8.7 MB to 1.7 MB. script/check-censored enforces the rest: it reads the name out of the vendoring script rather than repeating it, and fails on any occurrence in the working tree or under dist/ that is not one of the three literals shipped code cannot avoid — two provider-shim identifiers in src/content/inpage.js and one ERC-20's on-chain name in src/shared/tokenList.js. Each is permitted only at the path that carries it, and at the emitted paths that path is bundled into, so a literal appearing anywhere else fails like any other occurrence. It runs in make check, which inspects dist/ when there is one and says loudly when there is not, and again with --require-dist at the end of every make build. Removing the runtime fetch retires the delta, the extension-storage persistence and the 24-hour alarm from #158. A retired alarm is now cleared rather than left waking the worker forever on installs that already have it. The e2e suite drives the warning end to end from a real blocklisted origin served as a real http(s) site, with a control asserting the banner stays hidden for one that is not listed. Its service-worker interception canary needed a new anchor, since the startup fetch it used to watch for no longer happens: it now wakes the worker with a message and asks it for one throwaway fetch. LICENSE no longer cites a repository that returns 404. eslint.config.js gains one block: script/lib/ holds node programs the shell entrypoints call, and without it they lint with no globals at all.
106 lines
4.0 KiB
Bash
Executable File
106 lines
4.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/vendor-blocklist: refresh the vendored phishing blocklist at
|
|
# src/shared/phishingBlocklist.json from its upstream source. Our own extension
|
|
# to scripts-to-rule-them-all.
|
|
#
|
|
# This is build-time repo tooling and is not shipped. It is the one place in
|
|
# this repo that names the upstream project, because a source reference that
|
|
# does not say what the source is cannot be verified by anyone; the artifact it
|
|
# writes carries no names at all (see src/shared/domainHash.js).
|
|
# script/check-censored reads the name back out of this file rather than
|
|
# repeating it, so it stays defined exactly once.
|
|
#
|
|
# Run it deliberately, not on every build: the output is committed, and the
|
|
# extension does no runtime fetching, so the shipped list is exactly as fresh as
|
|
# the last time someone ran this and landed the result. Re-run it, land the
|
|
# diff, cut a release; that is the whole refresh path.
|
|
#
|
|
# Pinned by content hash, twice over, as REPO_POLICIES.md requires. The commit
|
|
# below is an immutable ref — the upstream default branch moves several times a
|
|
# day and cannot be pinned — and UPSTREAM_SHA256 is the sha256 of the bytes that
|
|
# commit serves. A mismatch is a hard failure: a vendoring step that accepts
|
|
# whatever it is handed is a supply-chain hole, and this one feeds a security
|
|
# warning shown to users.
|
|
#
|
|
# To move the pin: pick the new commit, run this with the new UPSTREAM_COMMIT
|
|
# and an UPSTREAM_SHA256 you have not yet updated, and it will print the hash it
|
|
# actually got. Verify that hash against the source independently before
|
|
# recording it. Never copy the "actual" line in on trust.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
# Upstream, pinned 2026-08-17.
|
|
UPSTREAM_ORG="MetaMask"
|
|
UPSTREAM_REPO="eth-phishing-detect"
|
|
UPSTREAM_COMMIT="6dddf74a87da3e1a0841f7ae0d1cb31aaf2c05db"
|
|
UPSTREAM_FILE="src/config.json"
|
|
UPSTREAM_SHA256="166d5b3504e8f4ed52eae37d3dd20c1a56efa0502bfb3dc957044ff8b5f1283f"
|
|
|
|
OUTPUT="src/shared/phishingBlocklist.json"
|
|
|
|
WORK=""
|
|
|
|
cleanup() {
|
|
[ -z "$WORK" ] || rm -rf "$WORK"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
fail() {
|
|
echo "vendor-blocklist: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
sha256_of() {
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
sha256sum "$1" | cut -d' ' -f1
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
shasum -a 256 "$1" | cut -d' ' -f1
|
|
else
|
|
fail "neither sha256sum nor shasum is available, so the fetched
|
|
source cannot be verified. Refusing to vendor unverified content."
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
|
|
command -v curl >/dev/null 2>&1 ||
|
|
fail "curl is required to fetch the upstream list"
|
|
command -v node >/dev/null 2>&1 ||
|
|
fail "node is required to build the artifact; run script/bootstrap"
|
|
|
|
WORK="$(mktemp -d "${TMPDIR:-/tmp}/autistmask-vendor-blocklist.XXXXXX")" ||
|
|
fail "could not create a working directory"
|
|
|
|
url="https://raw.githubusercontent.com/$UPSTREAM_ORG/$UPSTREAM_REPO/$UPSTREAM_COMMIT/$UPSTREAM_FILE"
|
|
echo "Fetching $url"
|
|
curl -fsSL --proto '=https' --tlsv1.2 -o "$WORK/source.json" "$url" ||
|
|
fail "the fetch failed, so nothing was vendored"
|
|
|
|
actual="$(sha256_of "$WORK/source.json")"
|
|
if [ "$actual" != "$UPSTREAM_SHA256" ]; then
|
|
fail "sha256 mismatch on the fetched source.
|
|
expected: $UPSTREAM_SHA256
|
|
actual: $actual
|
|
The pinned commit is immutable, so the same commit serving different bytes
|
|
means the content was substituted somewhere between upstream and here.
|
|
Nothing was written. Do not update the expectation to match unless you have
|
|
verified the new bytes independently."
|
|
fi
|
|
echo "Verified sha256 $actual"
|
|
|
|
node script/lib/build-blocklist.js "$WORK/source.json" "$WORK/out.json" ||
|
|
fail "the transform failed, so nothing was written"
|
|
|
|
if [ -f "$OUTPUT" ] && cmp -s "$WORK/out.json" "$OUTPUT"; then
|
|
echo "vendor-blocklist: $OUTPUT is already up to date"
|
|
return 0
|
|
fi
|
|
|
|
cp "$WORK/out.json" "$OUTPUT"
|
|
echo "vendor-blocklist: wrote $OUTPUT (sha256 $(sha256_of "$OUTPUT"))"
|
|
}
|
|
|
|
main "$@"
|