mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-21 22:52:19 +03:00
fix(security): add chatgpt-web-codex-doctor to SPAWN_CAPABLE_PATTERNS
The manage-scope bypass veto's precise early-deny keys on
SPAWN_CAPABLE_PATTERNS, but /api/providers/{id}/chatgpt-web-codex-doctor — a
LOCAL_ONLY route that spawns a subprocess via getTunnelRuntimeStatus() — was in
LOCAL_ONLY_API_PATTERNS without a matching spawn-capable pattern, so the two
layers had drifted. Add the pattern plus a regression test asserting every
regex-tier LOCAL_ONLY spawn route is covered, so the veto's exact early-deny
stays in sync with the tier.
Reported by @Zandereins via GHSA-9q3h-mjm5-f4gj (finding 1).
This commit is contained in:
@@ -52,6 +52,7 @@ export const SPAWN_CAPABLE_PATTERNS: ReadonlyArray<RegExp> = [
|
||||
/^\/api\/providers\/[^/]+\/login\/?$/, // pre-existing gap: in LOCAL_ONLY_API_PATTERNS today but never in a spawn-capable deny-list
|
||||
/^\/api\/providers\/[^/]+\/refresh-cursor\/?$/, // spawns cursor-agent via renewal.ts (Hard Rules #15 + #17)
|
||||
/^\/api\/providers\/cursor\/agent-availability\/?$/, // static path (no dynamic segment), but kept in this array alongside its /api/providers/ siblings rather than the flat SPAWN_CAPABLE_PREFIXES array — spawns cursor-agent status via checkCursorAgentAvailability()/getCachedCursorAgentAvailability() (Hard Rules #15 + #17)
|
||||
/^\/api\/providers\/[^/]+\/chatgpt-web-codex-doctor\/?$/, // spawns via getTunnelRuntimeStatus() → spawnSync("...","runtimes status") (open-sse/executors/chatgpt-web-codex/tunnelClient.ts). Mirrors LOCAL_ONLY_API_PATTERNS in routeGuard.ts; keep the two in sync (GHSA-9q3h-mjm5-f4gj).
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
isAlwaysProtectedPath,
|
||||
isLoopbackHost,
|
||||
} from "../../../src/server/authz/routeGuard.ts";
|
||||
import { SPAWN_CAPABLE_PATTERNS } from "../../../src/shared/constants/spawnCapablePrefixes.ts";
|
||||
import { managementPolicy } from "../../../src/server/authz/policies/management.ts";
|
||||
import { getMachineTokenSync } from "../../../src/lib/machineToken.ts";
|
||||
import { CLI_TOKEN_HEADER } from "../../../src/server/authz/headers.ts";
|
||||
@@ -50,6 +51,27 @@ test("isLocalOnlyBypassableByManageScope: non-local-only routes are not bypassab
|
||||
assert.equal(isLocalOnlyBypassableByManageScope("/api/settings"), false);
|
||||
});
|
||||
|
||||
test("SPAWN_CAPABLE_PATTERNS covers every regex-tier LOCAL_ONLY spawn route (GHSA-9q3h-mjm5-f4gj)", () => {
|
||||
// The manage-scope bypass veto's precise early-deny keys on
|
||||
// SPAWN_CAPABLE_PATTERNS, so every LOCAL_ONLY_API_PATTERNS entry (a
|
||||
// spawn-capable regex route) must have a matching pattern here — otherwise the
|
||||
// two layers drift and a spawn route loses its exact early-deny. This guards
|
||||
// against the chatgpt-web-codex-doctor drift and any future one.
|
||||
const spawnRoutes = [
|
||||
"/api/providers/acct-1/login",
|
||||
"/api/providers/acct-1/refresh-cursor",
|
||||
"/api/providers/acct-1/chatgpt-web-codex-doctor",
|
||||
];
|
||||
for (const p of spawnRoutes) {
|
||||
assert.equal(isLocalOnlyPath(p), true, `${p} must be LOCAL_ONLY`);
|
||||
assert.equal(
|
||||
SPAWN_CAPABLE_PATTERNS.some((re) => re.test(p)),
|
||||
true,
|
||||
`${p} is a LOCAL_ONLY spawn route but SPAWN_CAPABLE_PATTERNS does not cover it`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("isAlwaysProtectedPath: /api/shutdown is always protected", () => {
|
||||
assert.equal(isAlwaysProtectedPath("/api/shutdown"), true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user