harden: key remembered site permissions by full origin (closes #402)
allowedSites and deniedSites held the bare hostname, so a grant to https://dapp.example also authorised http://dapp.example and every port on that host, and the connection, transaction and signature prompts named only the hostname. Both lists now store and match the full origin (scheme://host[:port]), the key the connections approved without Remember already used. The prompts, the Settings site lists and AUTISTMASK_REMOVE_SITE use the origin too. Entries saved by hostname are not migrated (pre-1.0): they match no site. Model: opus-5-5
This commit is contained in:
@@ -59,24 +59,32 @@ describe("the floor under allowedSites and deniedSites", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test(`an ${field} entry whose value is not a hostname list is dropped`, () => {
|
||||
for (const bad of ["dapp.example", 42, null, { a: 1 }, true]) {
|
||||
test(`an ${field} entry whose value is not an origin list is dropped`, () => {
|
||||
for (const bad of [
|
||||
"https://dapp.example",
|
||||
42,
|
||||
null,
|
||||
{ a: 1 },
|
||||
true,
|
||||
]) {
|
||||
expect(
|
||||
normalizePersisted({ [field]: { [ADDRESS]: bad } })[field],
|
||||
).toEqual({});
|
||||
}
|
||||
});
|
||||
|
||||
test(`a hostname that is not text is dropped from an ${field} entry`, () => {
|
||||
test(`an origin that is not text is dropped from an ${field} entry`, () => {
|
||||
expect(
|
||||
normalizePersisted({
|
||||
[field]: { [ADDRESS]: [42, null, "dapp.example", {}] },
|
||||
[field]: {
|
||||
[ADDRESS]: [42, null, "https://dapp.example", {}],
|
||||
},
|
||||
})[field],
|
||||
).toEqual({ [ADDRESS]: ["dapp.example"] });
|
||||
).toEqual({ [ADDRESS]: ["https://dapp.example"] });
|
||||
});
|
||||
|
||||
test(`a real ${field} map survives, copied not shared`, () => {
|
||||
const saved = { [field]: { [ADDRESS]: ["dapp.example"] } };
|
||||
const saved = { [field]: { [ADDRESS]: ["https://dapp.example"] } };
|
||||
|
||||
const out = normalizePersisted(saved);
|
||||
|
||||
@@ -87,10 +95,13 @@ describe("the floor under allowedSites and deniedSites", () => {
|
||||
|
||||
test(`a good ${field} entry beside a malformed one survives`, () => {
|
||||
const out = normalizePersisted({
|
||||
[field]: { [ADDRESS]: ["dapp.example"], [TOKEN_ADDRESS]: 42 },
|
||||
[field]: {
|
||||
[ADDRESS]: ["https://dapp.example"],
|
||||
[TOKEN_ADDRESS]: 42,
|
||||
},
|
||||
});
|
||||
|
||||
expect(out[field]).toEqual({ [ADDRESS]: ["dapp.example"] });
|
||||
expect(out[field]).toEqual({ [ADDRESS]: ["https://dapp.example"] });
|
||||
});
|
||||
|
||||
test(`a stored own "__proto__" key in ${field} is dropped`, () => {
|
||||
@@ -100,7 +111,7 @@ describe("the floor under allowedSites and deniedSites", () => {
|
||||
// saveState()'s merge hands to the prototype setter on the next
|
||||
// write.
|
||||
const saved = JSON.parse(
|
||||
'{"' + field + '":{"__proto__":["evil.invalid"]}}',
|
||||
'{"' + field + '":{"__proto__":["https://evil.invalid"]}}',
|
||||
);
|
||||
|
||||
const out = normalizePersisted(saved);
|
||||
@@ -197,7 +208,7 @@ describe("a malformed allowedSites entry", () => {
|
||||
const MALFORMED = [
|
||||
{ name: "a string", value: "notalist" },
|
||||
{ name: "a number", value: 42 },
|
||||
{ name: "a record", value: { hostnames: ["dapp.example"] } },
|
||||
{ name: "a record", value: { origins: ["https://dapp.example"] } },
|
||||
];
|
||||
|
||||
for (const { name, value } of MALFORMED) {
|
||||
@@ -231,7 +242,7 @@ describe("a malformed allowedSites entry", () => {
|
||||
const env = await bootPopup(
|
||||
unversionedValidProfile({
|
||||
allowedSites: {
|
||||
[ADDRESS]: ["dapp.example"],
|
||||
[ADDRESS]: ["https://dapp.example"],
|
||||
[TOKEN_ADDRESS]: "notalist",
|
||||
},
|
||||
}),
|
||||
@@ -239,7 +250,7 @@ describe("a malformed allowedSites entry", () => {
|
||||
|
||||
expect(env.pageErrors).toEqual([]);
|
||||
expect(env.storage.read("autistmask").allowedSites).toEqual({
|
||||
[ADDRESS]: ["dapp.example"],
|
||||
[ADDRESS]: ["https://dapp.example"],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user