Files
devplacepy/nodes/extension/test/policy.test.mjs
T
retoor 6f80a820da
DevPlace CI / test (push) Failing after 3m13s
Zo doen wijdat in oost
2026-10-16 07:20:44 +02:00

115 lines
4.6 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { Policy } from "../src/Policy.js";
import { DESTINATIONS, REFUSALS } from "../src/spec.js";
const policy = new Policy();
test("allows https on the allowlisted hosts and subdomains", () => {
for (const url of [
"https://reddit.com/r/python.json",
"https://www.reddit.com/r/python.json",
"https://old.reddit.com/",
"https://redd.it/abc",
"https://REDDIT.COM./x",
]) {
assert.equal(policy.check("GET", url).ok, true, url);
}
});
test("suffix matching is dot safe", () => {
for (const url of [
"https://evilreddit.com/",
"https://reddit.com.evil.net/",
"https://notredd.it/",
"https://reddit.co/",
]) {
const verdict = policy.check("GET", url);
assert.equal(verdict.ok, false, url);
assert.equal(verdict.code, REFUSALS.HOST_NOT_ALLOWED);
}
});
test("userinfo tricks are refused", () => {
for (const url of [
"https://reddit.com@evil.net/",
"https://user:pass@reddit.com/",
"https://evil.net\\@reddit.com/",
]) {
assert.equal(policy.check("GET", url).ok, false, url);
}
});
test("non https schemes are refused", () => {
for (const url of ["http://reddit.com/", "ftp://reddit.com/", "ws://reddit.com/", "file:///etc/passwd"]) {
const verdict = policy.check("GET", url);
assert.equal(verdict.ok, false, url);
}
});
test("only port 443 passes over https", () => {
assert.equal(policy.check("GET", "https://reddit.com:443/").ok, true);
for (const url of ["https://reddit.com:80/", "https://reddit.com:8443/", "https://reddit.com:22/"]) {
const verdict = policy.check("GET", url);
assert.equal(verdict.ok, false, url);
assert.equal(verdict.code, REFUSALS.PORT_NOT_ALLOWED);
}
});
test("method must be permitted", () => {
const verdict = policy.check("POST", "https://reddit.com/");
assert.equal(verdict.code, REFUSALS.METHOD_NOT_ALLOWED);
assert.equal(policy.check("get", "https://reddit.com/").ok, true);
});
test("ip literals, junk and oversize urls are refused", () => {
for (const url of ["https://127.0.0.1/", "https://[::1]/", "https://10.0.0.1/", "nonsense", "", null, 5]) {
assert.equal(policy.check("GET", url).ok, false, String(url));
}
assert.equal(policy.check("GET", "https://reddit.com/" + "a".repeat(3000)).ok, false);
});
test("a redirect leaving the allowlist is refused with redirect_not_allowed", () => {
const base = new URL("https://www.reddit.com/r/x");
const bad = policy.checkRedirect("https://evil.net/landing", base, "GET");
assert.equal(bad.ok, false);
assert.equal(bad.code, REFUSALS.REDIRECT_NOT_ALLOWED);
assert.equal(policy.checkRedirect("http://reddit.com/x", base, "GET").code, REFUSALS.REDIRECT_NOT_ALLOWED);
assert.equal(policy.checkRedirect("//evilreddit.com/x", base, "GET").code, REFUSALS.REDIRECT_NOT_ALLOWED);
assert.equal(policy.checkRedirect("/r/y", base, "GET").ok, true);
assert.equal(policy.checkRedirect("https://old.reddit.com/r/y", base, "GET").ok, true);
});
test("a refreshed allowlist may only be equal or narrower", () => {
const narrower = [{ ...DESTINATIONS[0], suffix: "old.reddit.com" }];
const kept = Policy.narrow(DESTINATIONS, narrower);
assert.equal(kept.destinations.length, 1);
assert.equal(kept.rejected.length, 0);
const equal = Policy.narrow(DESTINATIONS, DESTINATIONS.map((item) => ({ ...item })));
assert.equal(equal.destinations.length, DESTINATIONS.length);
const widened = Policy.narrow(DESTINATIONS, [
{ suffix: "evil.net", adapter: "x", methods: ["GET"], ports: [443], modes: ["fetch"] },
{ suffix: "reddit.com", adapter: "reddit", methods: ["GET", "POST"], ports: [443], modes: ["fetch"] },
{ suffix: "reddit.com", adapter: "reddit", methods: ["GET"], ports: [443, 8080], modes: ["fetch"] },
{ suffix: "reddit.com", adapter: "reddit", methods: ["GET"], ports: [443], modes: ["tunnel"] },
{ suffix: "evilreddit.com", adapter: "reddit", methods: ["GET"], ports: [443], modes: ["fetch"] },
]);
assert.equal(widened.destinations.length, 0);
assert.equal(widened.rejected.length, 5);
const empty = Policy.narrow(DESTINATIONS, []);
assert.equal(empty.destinations.length, 0);
assert.equal(Policy.narrow(DESTINATIONS, "x").destinations.length, 0);
});
test("a narrowed policy refuses what the baked policy would allow", () => {
const { policy: narrow } = Policy.fromRefreshed(DESTINATIONS, [
{ ...DESTINATIONS[0], suffix: "old.reddit.com" },
]);
assert.equal(narrow.check("GET", "https://old.reddit.com/").ok, true);
assert.equal(narrow.check("GET", "https://www.reddit.com/").ok, false);
assert.equal(narrow.check("GET", "https://redd.it/x").ok, false);
});