Compare commits

..

3 Commits

Author SHA1 Message Date
adevwithpurpose
af6813ca12 fix(security): keep only the regex sanitization; drop non-functional CodeQL annotations
The lgtm[]/nosemgrep: comments in codexIdentity.ts and reasoningCache.ts use
formats GitHub Actions CodeQL does not honor, and shifting those sha256 lines
re-attributed the already-dismissed base alerts to this PR as two new CodeQL
findings. Revert those two annotation-only files to base so the existing
dismissals apply; retain the real fix (escaping backslash in the test regex),
which resolves the open js/incomplete-sanitization alert.
2026-08-15 10:08:14 -03:00
adevwithpurpose
864e817eda Merge remote-tracking branch 'origin/release/v3.8.50' into fix/codeql-0814-hash-fp-and-sanitize 2026-08-15 09:04:23 -03:00
Xiangzhe
ab36b35035 fix(security): sanitize test regex and annotate CodeQL hash false-positives
tests/unit/early-sse-route-intent.test.ts built a RegExp from a hardcoded
string but only escaped `?`/`.`, missing `\` — js/incomplete-sanitization
(#816). Not exploitable (fixed literal input) but the escaping was
genuinely incomplete; now escapes backslash too.

reasoningCache.ts::buildAssistantMessageCacheKey and codexIdentity.ts's two
UUID derivation helpers hash a cache-scope/account-seed with SHA-256 to
produce a lookup key / deterministic ID — not a stored, verified password.
CodeQL's js/insufficient-password-hash overfires on any hash of a
secret-like variable, the same false-positive class already annotated at
src/lib/db/apiKeys.ts:624. Added matching lgtm/nosemgrep annotations and
inline rationale so the intent is clear to reviewers and future scans.

Refs #815 #816 #817 #818
2026-08-14 10:07:07 -03:00
4 changed files with 3 additions and 65 deletions

View File

@@ -1 +0,0 @@
- fix(providers): GitLab Duo falls back to the public Code Suggestions endpoint when direct_access returns 401 (#10365)

View File

@@ -583,20 +583,10 @@ export class GitlabExecutor extends BaseExecutor {
}
if (response.status === 401) {
if (input.log) {
input.log.warn(
"GITLAB-DUO",
"direct_access exchange rejected (401); falling back to public completions endpoint"
);
}
return {
target: {
mode: "monolith",
url: endpoints.publicCompletionsUrl,
headers: buildMonolithHeaders(credentials.accessToken || null),
},
target: null,
credentials,
errorResponse: null,
errorResponse: toOpenAIError(401, "GitLab Duo direct access token request was rejected"),
};
}

View File

@@ -22,7 +22,7 @@ const ROUTES = [
for (const route of ROUTES) {
test(`${route.name} early-heartbeat gate uses the real stream resolver`, () => {
const escapedBodyExpression = route.bodyExpression.replace(/[?.]/g, "\\$&");
const escapedBodyExpression = route.bodyExpression.replace(/[.?\\]/g, "\\$&");
assert.match(
route.source,
new RegExp(

View File

@@ -261,54 +261,3 @@ test("GitlabExecutor falls back to the public Code Suggestions endpoint when dir
globalThis.fetch = originalFetch;
}
});
// #10365: a 401 from the direct_access exchange must ALSO fall back to the public
// Code Suggestions completions endpoint (same resilience as the 403-disabled case
// above), instead of surfacing an opaque 401 token error with no fallback.
test("GitlabExecutor falls back to the public Code Suggestions endpoint when direct_access returns 401", async () => {
const executor = getExecutor("gitlab-duo") as GitlabExecutor;
const originalFetch = globalThis.fetch;
const calls: string[] = [];
globalThis.fetch = async (url) => {
calls.push(String(url));
if (String(url) === "https://gitlab.example.com/api/v4/code_suggestions/direct_access") {
return jsonResponse({ error: "invalid_token" }, 401);
}
return jsonResponse({
model: { name: "code-gecko" },
choices: [{ text: "monolith fallback works" }],
});
};
try {
const result = await executor.execute({
model: "gitlab-duo-code-suggestions",
body: {
messages: [{ role: "user", content: "Say hello" }],
},
stream: false,
credentials: {
accessToken: "oauth-access",
providerSpecificData: {
baseUrl: "https://gitlab.example.com",
},
},
signal: AbortSignal.timeout(10_000),
log: null,
});
assert.deepEqual(calls, [
"https://gitlab.example.com/api/v4/code_suggestions/direct_access",
"https://gitlab.example.com/api/v4/code_suggestions/completions",
]);
const body = (await result.response.json()) as any;
assert.equal(body.model, "code-gecko");
assert.match(body.choices[0].message.content, /monolith fallback works/i);
} finally {
globalThis.fetch = originalFetch;
}
});