security: announce a fresh EIP-6963 provider UUID per page load (closes #398)
e2e / e2e-chrome (push) Failing after 0s
e2e / e2e-firefox (push) Failing after 0s
check / check (push) Successful in 44s

The provider UUID was generated once, stored in extension storage, and
announced verbatim to every page on every load and across restarts, so any
site — connected or not — could read a stable cross-site, cross-session
identifier for the install: a supercookie contradicting the "no tracking"
promise. EIP-6963 wants a fresh UUIDv4 per announcement instead.

inpage.js now announces a per-load crypto.randomUUID() and persists nothing;
the eip6963Uuid storage key and the AUTISTMASK_PROVIDER_UUID content-script
message are removed. That key was a standalone top-level storage entry, never
part of the versioned autistmask profile, so stateSchema.js and the
persisted-field harness are untouched and no existing profile is affected.

A jest test asserts two loads announce different UUIDv4s and that one load
reuses a single UUID across re-announcements.

Model: opus-4-8
This commit is contained in:
2026-09-21 23:35:57 +00:00
parent 598de3ff1a
commit 60d2b24cd1
5 changed files with 127 additions and 42 deletions
+5 -5
View File
@@ -372,10 +372,10 @@ step("the loopback dApp page gets the real inpage provider", async (env) => {
STEP_TIMEOUT_MS,
);
// EIP-6963, asked of the provider itself. The announcement carries the
// uuid src/content/index.js reads out of extension storage — call site 1
// in the issue and it has to name this extension and hand back the very
// object on window.ethereum.
// EIP-6963, asked of the provider itself. The announcement carries a
// UUIDv4 inpage.js generates fresh for this page load (nothing persists
// it — see issue #398) and has to name this extension and hand back the
// very object on window.ethereum.
const announced = await d.executeAsync(
`const done = arguments[arguments.length - 1];
const onAnnounce = (e) => {
@@ -402,7 +402,7 @@ step("the loopback dApp page gets the real inpage provider", async (env) => {
);
assert(
typeof announced.uuid === "string" && announced.uuid.length === 36,
"the announcement carries no stored provider uuid: " +
"the announcement carries no provider uuid: " +
JSON.stringify(announced.uuid),
);