fix(qoder): reject invalid/expired PATs returning Cosy 500 error (#2860)

Integrated into release/v3.8.6.
This commit is contained in:
Hernan Javier Ardila Sanchez
2026-05-29 05:56:19 +02:00
committed by GitHub
parent f3404227d2
commit 94a34899b2
2 changed files with 54 additions and 0 deletions

View File

@@ -505,6 +505,22 @@ export async function validateQoderCliPat({
// Treat 5xx as valid bypass to prevent false negatives from legacy Qoder APIs (issue #1391)
if (res.status >= 500) {
const isCosyAppError =
/"success"\s*:\s*false/.test(errorDetail) &&
(/"msgCode"\s*:\s*500/.test(errorDetail) || /internal\s*server\s*error/i.test(errorDetail));
if (isCosyAppError) {
return {
valid: false,
error:
`Authentication failed (HTTP ${res.status}). The Qoder Cosy server returned an Internal Server Error. ` +
"This typically indicates that your Personal Access Token is invalid, expired, or not authorized. " +
"Please check your token at https://qoder.com/account/integrations." +
(errorDetail ? ` Server response: ${errorDetail}` : ""),
unsupported: false,
};
}
return {
valid: true,
error: `Validation endpoint returned HTTP ${res.status}${errorDetail ? `: ${errorDetail}` : ""}, treating PAT as valid`,

View File

@@ -364,3 +364,41 @@ test("validateQoderCliPat treats 5xx HTTP failures as valid bypass", async () =>
globalThis.fetch = originalFetch;
}
});
test("validateQoderCliPat rejects 500 HTTP failures if response is Cosy app-level auth error", async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url) => {
if (String(url).includes("/ping")) return new Response("pong", { status: 200 });
return new Response(
' { "success" : false, "traceId": "a4e5de61929400b9243b4f6e49756906", "msgCode" : 500 } ',
{ status: 500 }
);
};
try {
const result = await qoderCli.validateQoderCliPat({ apiKey: "invalid-pat" });
assert.equal(result.valid, false);
assert.match(result.error!, /Authentication failed \(HTTP 500\)/);
} finally {
globalThis.fetch = originalFetch;
}
});
test("validateQoderCliPat rejects 500 HTTP failures using regex for Internal Server Error with whitespace", async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url) => {
if (String(url).includes("/ping")) return new Response("pong", { status: 200 });
return new Response(
' { "success" : false, "error": "Internal Server Error" } ',
{ status: 500 }
);
};
try {
const result = await qoderCli.validateQoderCliPat({ apiKey: "invalid-pat" });
assert.equal(result.valid, false);
assert.match(result.error!, /Authentication failed \(HTTP 500\)/);
} finally {
globalThis.fetch = originalFetch;
}
});