mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 21:32:20 +03:00
106 lines
4.3 KiB
TypeScript
106 lines
4.3 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const mod = await import("../../src/lib/proxySubscription/coreEndpoint.ts");
|
|
const {
|
|
isLocalCoreEndpointAllowed,
|
|
ALLOWED_LOCAL_CORE_HOSTS,
|
|
parseLocalCoreEndpoints,
|
|
redactCoreEntryForDetail,
|
|
} = mod;
|
|
|
|
test("loopback hosts are allowed", () => {
|
|
assert.equal(isLocalCoreEndpointAllowed("socks5://127.0.0.1:1080"), true);
|
|
assert.equal(isLocalCoreEndpointAllowed("http://localhost:2080"), true);
|
|
});
|
|
|
|
test("remote hosts are rejected", () => {
|
|
assert.equal(isLocalCoreEndpointAllowed("socks5://10.0.0.1:1080"), false);
|
|
assert.equal(isLocalCoreEndpointAllowed("http://example.com:2080"), false);
|
|
assert.equal(isLocalCoreEndpointAllowed("https://192.168.1.1:443"), false);
|
|
});
|
|
|
|
test("non-proxy schemes on loopback are rejected", () => {
|
|
assert.equal(isLocalCoreEndpointAllowed("ftp://127.0.0.1:21"), false);
|
|
assert.equal(isLocalCoreEndpointAllowed("file:///tmp/core.sock"), false);
|
|
});
|
|
|
|
test("null / empty / malformed endpoints are rejected", () => {
|
|
assert.equal(isLocalCoreEndpointAllowed(null), false);
|
|
assert.equal(isLocalCoreEndpointAllowed(""), false);
|
|
assert.equal(isLocalCoreEndpointAllowed("not a url"), false);
|
|
});
|
|
|
|
test("allowed host set is loopback-only", () => {
|
|
assert.deepEqual([...ALLOWED_LOCAL_CORE_HOSTS].sort(), ["127.0.0.1", "::1", "localhost"].sort());
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints splits one entry per line", () => {
|
|
assert.deepEqual(
|
|
parseLocalCoreEndpoints(
|
|
"socks5://127.0.0.1:1080\nsocks5://127.0.0.1:1081\nhttp://localhost:2080"
|
|
),
|
|
["socks5://127.0.0.1:1080", "socks5://127.0.0.1:1081", "http://localhost:2080"]
|
|
);
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints handles CRLF and drops blank lines", () => {
|
|
assert.deepEqual(
|
|
parseLocalCoreEndpoints("socks5://127.0.0.1:1080\r\n\r\n \r\nsocks5://127.0.0.1:1081\r\n"),
|
|
["socks5://127.0.0.1:1080", "socks5://127.0.0.1:1081"]
|
|
);
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints trims each line", () => {
|
|
assert.deepEqual(
|
|
parseLocalCoreEndpoints(" socks5://127.0.0.1:1080 \n\tsocks5://127.0.0.1:1081\t"),
|
|
["socks5://127.0.0.1:1080", "socks5://127.0.0.1:1081"]
|
|
);
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints never splits on commas", () => {
|
|
// A comma is legitimate inside userinfo; it must survive the split.
|
|
assert.deepEqual(parseLocalCoreEndpoints("socks5://user,name:pass@127.0.0.1:1080"), [
|
|
"socks5://user,name:pass@127.0.0.1:1080",
|
|
]);
|
|
// Two URLs on one comma-separated line are a single entry (rejected by the
|
|
// loopback gate later, not by the parser).
|
|
assert.deepEqual(parseLocalCoreEndpoints("socks5://127.0.0.1:1080, socks5://127.0.0.1:1081"), [
|
|
"socks5://127.0.0.1:1080, socks5://127.0.0.1:1081",
|
|
]);
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints returns [] for null or blank input", () => {
|
|
assert.deepEqual(parseLocalCoreEndpoints(null), []);
|
|
assert.deepEqual(parseLocalCoreEndpoints(""), []);
|
|
assert.deepEqual(parseLocalCoreEndpoints(" \n \r\n "), []);
|
|
});
|
|
|
|
test("parseLocalCoreEndpoints keeps a port-less entry as-is", () => {
|
|
// The default port (8080 per the upsert rule) is applied in the sync loop.
|
|
assert.deepEqual(parseLocalCoreEndpoints("socks5://127.0.0.1"), ["socks5://127.0.0.1"]);
|
|
});
|
|
|
|
test("redactCoreEntryForDetail strips userinfo from parseable entries", () => {
|
|
const redacted = redactCoreEntryForDetail("socks5://user:pass@127.0.0.1:1080");
|
|
assert.ok(!redacted.includes("user"), `userinfo leaked: ${redacted}`);
|
|
assert.ok(!redacted.includes("pass"), `password leaked: ${redacted}`);
|
|
assert.ok(redacted.includes("127.0.0.1:1080"));
|
|
});
|
|
|
|
test("redactCoreEntryForDetail leaves entries without userinfo unchanged", () => {
|
|
assert.equal(redactCoreEntryForDetail("socks5://127.0.0.1:1080"), "socks5://127.0.0.1:1080");
|
|
});
|
|
|
|
test("redactCoreEntryForDetail strips userinfo even from malformed entries", () => {
|
|
const redacted = redactCoreEntryForDetail("socks5://user:pass@???");
|
|
assert.ok(!redacted.includes("user"), `userinfo leaked: ${redacted}`);
|
|
assert.ok(!redacted.includes("pass"), `password leaked: ${redacted}`);
|
|
});
|
|
|
|
test("redactCoreEntryForDetail keeps a @ in the path of malformed entries", () => {
|
|
// No authority userinfo here (no scheme, @ after a path slash): kept
|
|
// verbatim so the stored detail stays diagnosable.
|
|
assert.equal(redactCoreEntryForDetail("not-a-url/path@seg"), "not-a-url/path@seg");
|
|
});
|