Files
OmniRoute/tests/unit/claude-oauth-provider.test.ts
diegosouzapw 871f0520bb fix(security): mask public upstream creds + centralize error sanitization
Embed Gemini, Antigravity and Windsurf public OAuth/Firebase identifiers
(extracted from upstream CLI binaries) through a XOR-masked byte sequence
in open-sse/utils/publicCreds.ts instead of source literals, so pattern
scanners (GitHub Secret Scanning, Semgrep) stop raising false positives on
every release. decodePublicCred passes raw values through unchanged for
users who already have plaintext in their .env (no migration needed).

- New utils/publicCreds.ts with decode/encode + tests
- Replace 6 hardcoded Google client_id/secret in oauth.ts + providerRegistry
- Drop literals from .env.example (comment-only documentation)
- Sanitize error messages inside buildErrorBody so every caller (incl.
  createErrorResult) is covered; cursor.ts now reuses the shared helper
- Cover the new helpers with unit tests (publicCreds + error sanitization)

Resolves the open code-scanning js/stack-trace-exposure findings and the
secret-scanning Google API Key alert without breaking existing setups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:38:13 -03:00

105 lines
3.7 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
// Public OAuth client_id/secret defaults for Gemini, Antigravity and Windsurf
// are resolved at module load through open-sse/utils/publicCreds.ts — no need
// to populate them here. Only the providers without a baked-in default need
// explicit env setup for this suite.
Object.assign(process.env, {
CLAUDE_OAUTH_CLIENT_ID: "9d1c250a-e61b-44d9-88ed-5944d1962f5e",
CODEX_OAUTH_CLIENT_ID: "app_EMoamEEZ73f0CkXaXp7hrann",
QWEN_OAUTH_CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56",
KIMI_CODING_OAUTH_CLIENT_ID: "17e5f671-d194-4dfb-9706-5516cb48c098",
GITHUB_OAUTH_CLIENT_ID: "Iv1.b507a08c87ecfe98",
});
const { claude } = await import("../../src/lib/oauth/providers/claude.ts");
const { CLAUDE_CONFIG } = await import("../../src/lib/oauth/constants/oauth.ts");
const originalFetch = globalThis.fetch;
test.afterEach(() => {
globalThis.fetch = originalFetch;
});
test("Claude OAuth provider always uses the configured redirectUri when building the auth URL", () => {
const runtimeRedirectUri = "http://localhost:43121/callback";
const authUrl = claude.buildAuthUrl(
CLAUDE_CONFIG,
runtimeRedirectUri,
"state-123",
"challenge-456"
);
const parsed = new URL(authUrl);
assert.equal(parsed.searchParams.get("redirect_uri"), CLAUDE_CONFIG.redirectUri);
assert.equal(parsed.searchParams.get("state"), "state-123");
assert.equal(parsed.searchParams.get("code_challenge"), "challenge-456");
});
test("Claude OAuth provider always uses the configured redirectUri during token exchange", async () => {
let captured = null;
globalThis.fetch = async (url, init = {}) => {
captured = {
url: String(url),
method: init.method,
headers: init.headers,
body: JSON.parse(String(init.body)),
};
return new Response(JSON.stringify({ access_token: "token-1" }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
const runtimeRedirectUri = "http://localhost:43121/callback";
await claude.exchangeToken(
CLAUDE_CONFIG,
"auth-code#state-from-fragment",
runtimeRedirectUri,
"verifier-123",
"state-from-request"
);
assert.equal(captured.url, CLAUDE_CONFIG.tokenUrl);
assert.equal(captured.method, "POST");
assert.equal(captured.body.redirect_uri, CLAUDE_CONFIG.redirectUri);
assert.equal(captured.body.code, "auth-code");
assert.equal(captured.body.state, "state-from-fragment");
assert.equal(captured.body.code_verifier, "verifier-123");
});
test("Claude OAuth token mapper persists the first non-empty token plan field", () => {
const cases = [
[{ account_tier: " Pro ", plan: "Max" }, "Pro"],
[{ account_tier: "", plan: "Max" }, "Max"],
[{ plan: "", subscription_type: "Team" }, "Team"],
[{ subscription_type: "", billing: { plan: "Enterprise" } }, "Enterprise"],
];
for (const [tokens, expected] of cases) {
const mapped = claude.mapTokens({ access_token: "token-1", ...tokens });
assert.equal(mapped.providerSpecificData.plan, expected);
}
});
test("Claude OAuth token mapper reads plan fields from userinfo extras after token fields", () => {
const mapped = claude.mapTokens(
{ access_token: "token-1" },
{ userInfo: { account_tier: "", subscription_type: "Max" } }
);
assert.equal(mapped.providerSpecificData.plan, "Max");
});
test("Claude OAuth token mapper leaves providerSpecificData.plan undefined without plan fields", () => {
const mapped = claude.mapTokens({ access_token: "token-1", scope: "user:profile" });
assert.ok(mapped.providerSpecificData);
assert.ok(typeof mapped.providerSpecificData.cliUserID === "string");
assert.equal(mapped.providerSpecificData.plan, undefined);
});