65 lines
4.0 KiB
JavaScript
65 lines
4.0 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { BrowserAccessPolicy } from "../src/access-policy.js";
|
|
|
|
test("browser policy requires at least one exact HTTP origin", () => {
|
|
assert.throws(() => new BrowserAccessPolicy([]), /must not be empty/);
|
|
assert.throws(() => new BrowserAccessPolicy(["file:///tmp"]), /HTTP/);
|
|
assert.throws(() => new BrowserAccessPolicy(["http://app:5173/path"]), /origin/);
|
|
});
|
|
|
|
test("browser policy permits exact allowed origins and rejects SSRF destinations", () => {
|
|
const policy = new BrowserAccessPolicy(["http://dev-server-worker:5173"]);
|
|
assert.equal(policy.assertUrl("http://dev-server-worker:5173/dashboard", { navigation: true }), "http://dev-server-worker:5173/dashboard");
|
|
assert.throws(() => policy.assertUrl("http://dev-server-worker:3000/mcp", { navigation: true }), /not allowed/);
|
|
assert.throws(() => policy.assertUrl("http://169.254.169.254/latest/meta-data", { navigation: true }), /not allowed/);
|
|
assert.throws(() => policy.assertUrl("file:///etc/passwd", { navigation: true }), /not allowed/);
|
|
assert.throws(() => policy.assertUrl("http://user:pass@dev-server-worker:5173/", { navigation: true }), /not allowed/);
|
|
assert.equal(policy.assertWebSocketUrl("ws://dev-server-worker:5173/socket"), "ws://dev-server-worker:5173/socket");
|
|
assert.throws(() => policy.assertWebSocketUrl("ws://dev-server-worker:3000/mcp"), /not allowed/);
|
|
});
|
|
|
|
test("auxiliary data URLs are allowed only for subresources", () => {
|
|
const policy = new BrowserAccessPolicy(["https://app.example"]);
|
|
assert.match(policy.assertUrl("data:text/plain,ok"), /^data:/);
|
|
assert.throws(() => policy.assertUrl("data:text/html,hello", { navigation: true }), /not allowed/);
|
|
});
|
|
|
|
test("a port range covers every port an execution may be given", () => {
|
|
// One entry instead of one per concurrent execution: an allowlist that has to be rewritten as
|
|
// executions come and go is an allowlist somebody will eventually replace with a wildcard.
|
|
const policy = new BrowserAccessPolicy(["http://dev-server-worker:5200-5219"]);
|
|
|
|
assert.equal(policy.assertUrl("http://dev-server-worker:5200/", { navigation: true }), "http://dev-server-worker:5200/");
|
|
assert.equal(policy.assertUrl("http://dev-server-worker:5219/app", { navigation: true }), "http://dev-server-worker:5219/app");
|
|
assert.throws(() => policy.assertUrl("http://dev-server-worker:5220/", { navigation: true }), /not allowed/);
|
|
assert.throws(() => policy.assertUrl("http://dev-server-worker:5199/", { navigation: true }), /not allowed/);
|
|
});
|
|
|
|
test("a range widens the port and nothing else", () => {
|
|
const policy = new BrowserAccessPolicy(["http://dev-server-worker:5200-5219"]);
|
|
|
|
assert.throws(() => policy.assertUrl("http://elsewhere:5200/", { navigation: true }), /not allowed/);
|
|
assert.throws(() => policy.assertUrl("https://dev-server-worker:5200/", { navigation: true }), /not allowed/);
|
|
});
|
|
|
|
test("hot reload is allowed as far as the page it belongs to", () => {
|
|
const policy = new BrowserAccessPolicy(["http://dev-server-worker:5200-5219"]);
|
|
|
|
assert.equal(policy.assertWebSocketUrl("ws://dev-server-worker:5207/?token=x"), "ws://dev-server-worker:5207/?token=x");
|
|
assert.throws(() => policy.assertWebSocketUrl("ws://dev-server-worker:5300/"), /not allowed/);
|
|
});
|
|
|
|
test("exact origins and ranges live together", () => {
|
|
const policy = new BrowserAccessPolicy(["http://fixed-app:8080", "http://dev-server-worker:5200-5201"]);
|
|
|
|
assert.equal(policy.assertUrl("http://fixed-app:8080/", { navigation: true }), "http://fixed-app:8080/");
|
|
assert.equal(policy.assertUrl("http://dev-server-worker:5201/", { navigation: true }), "http://dev-server-worker:5201/");
|
|
assert.throws(() => policy.assertUrl("http://fixed-app:8081/", { navigation: true }), /not allowed/);
|
|
});
|
|
|
|
test("an impossible range is refused at startup, not at the first navigation", () => {
|
|
assert.throws(() => new BrowserAccessPolicy(["http://app:5219-5200"]), /impossible port range/);
|
|
assert.throws(() => new BrowserAccessPolicy(["http://app:5200-99999"]), /impossible port range/);
|
|
});
|