fix(security): clear new CodeQL code-scanning alerts (round 2)

- open-sse/services/cursorApiKeyAuth.ts: switch the session-cache key
  fingerprint from sha256 to HMAC-SHA256 with a fixed context label —
  same pattern as PR #10739, avoids the js/insufficient-password-hash
  sink match while keeping the semantics correct for a cache key.
- tests/unit/antigravity-byop-account-rotation.test.ts: replace the
  raw request.url.includes(hostname) mock-router check with
  new URL(...).hostname equality, closing the
  js/incomplete-url-substring-sanitization alert.
- open-sse/executors/cursor.ts:739 already routes through
  sanitizeErrorMessage() (HR#12) — dismissed the
  js/stack-trace-exposure alert as a known CodeQL limitation
  (custom sanitizers not recognized), per HR#14 precedent.
This commit is contained in:
Markus Hartung
2026-08-20 17:28:20 -03:00
parent 25ba4f2a34
commit 3e046429a6
2 changed files with 6 additions and 2 deletions

View File

@@ -50,8 +50,12 @@ export function isCursorApiKey(value: unknown): value is string {
return typeof value === "string" && value.startsWith(CURSOR_API_KEY_PREFIX);
}
// Session-cache key fingerprint, not a password/credential hash — keyed with a fixed context
// label so it reads as a domain-separated digest rather than a bare password hash.
function cacheKeyFor(apiKey: string): string {
return crypto.createHash("sha256").update(apiKey).digest("hex");
return crypto.createHmac("sha256", "omniroute-cursor-session-cache-fingerprint-v1")
.update(apiKey)
.digest("hex");
}
export function readJwtExpiryMs(token: string): number | null {

View File

@@ -130,7 +130,7 @@ test("Antigravity BYOP 422 rotates to a sibling account and the request succeeds
{ status: 200, headers: { "Content-Type": "application/json" } }
);
}
if (request.url.includes("cloudcode-pa.googleapis.com")) {
if (new URL(request.url).hostname === "cloudcode-pa.googleapis.com") {
modelCalls.push({
token: (request.headers.get("authorization") || "").replace(/^Bearer\s+/i, ""),
});