mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 20:52:15 +03:00
fix(api): hash API keys in the v1 models catalog cache key
Validated in local merge-train-equivalent focused gate on release/v3.8.50 tip 9081b57146: catalog fingerprint regression + existing catalog-cache callers, 8 tests passed.
This commit is contained in:
1
changelog.d/fixes/catalog-cache-hash-apikey.md
Normal file
1
changelog.d/fixes/catalog-cache-hash-apikey.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(api):** hash API keys in the `/v1/models` catalog cache Map key so heap dumps cannot leak bearer tokens (`src/app/api/v1/models/catalogCache.ts`)
|
||||
@@ -12,11 +12,19 @@
|
||||
* Auth rejection is NOT handled here and must stay in the caller: it depends on
|
||||
* live per-request state (dashboard cookie, API key) and must never be cached.
|
||||
*/
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
import { getModelCatalogCacheVersion } from "@/lib/db/readCache";
|
||||
import { extractApiKey } from "@/sse/services/auth";
|
||||
|
||||
import { isCodexModelCatalogClient } from "./catalogRequest";
|
||||
|
||||
/** Fingerprint an API key for the catalog memo Map. Never store the raw secret. */
|
||||
export function fingerprintCatalogAuthKey(apiKey: string): string {
|
||||
if (!apiKey) return "";
|
||||
return createHash("sha256").update(apiKey).digest("hex").slice(0, 16);
|
||||
}
|
||||
|
||||
export type CachedCatalog = {
|
||||
body: string;
|
||||
headers: Record<string, string>;
|
||||
@@ -96,7 +104,7 @@ function buildCatalogCacheKey(
|
||||
const configuredOnly = url.searchParams.get("configuredOnly") === "true" ? "1" : "0";
|
||||
const hideAuto = catalogSettings?.hideAutoCombos ? "1" : "0";
|
||||
const hideNoThink = catalogSettings?.hideNoThinkVariants ? "1" : "0";
|
||||
return `${prefix}|${isCodex}|${apiKey}|${configuredOnly}|${hideAuto}|${hideNoThink}`;
|
||||
return `${prefix}|${isCodex}|${fingerprintCatalogAuthKey(apiKey)}|${configuredOnly}|${hideAuto}|${hideNoThink}`;
|
||||
}
|
||||
|
||||
// Tracks the model-catalog cache version (src/lib/db/readCache.ts) as of the last
|
||||
|
||||
15
tests/unit/catalog-cache-auth-fingerprint.test.ts
Normal file
15
tests/unit/catalog-cache-auth-fingerprint.test.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
|
||||
import { fingerprintCatalogAuthKey } from "../../src/app/api/v1/models/catalogCache.ts";
|
||||
|
||||
test("fingerprintCatalogAuthKey never returns the raw API key", () => {
|
||||
const raw = "sk-test-super-secret-catalog-key";
|
||||
const finger = fingerprintCatalogAuthKey(raw);
|
||||
assert.equal(finger.length, 16);
|
||||
assert.equal(finger.includes(raw), false);
|
||||
assert.equal(finger.includes("sk-test"), false);
|
||||
assert.equal(fingerprintCatalogAuthKey(raw), finger);
|
||||
assert.notEqual(fingerprintCatalogAuthKey("sk-other"), finger);
|
||||
assert.equal(fingerprintCatalogAuthKey(""), "");
|
||||
});
|
||||
Reference in New Issue
Block a user