fix(auth): harden unified diagnostic execution

This commit is contained in:
2026-08-17 16:39:54 +02:00
parent 3ed00ff086
commit 30ee9433dc
20 changed files with 1034 additions and 57 deletions
+23
View File
@@ -136,3 +136,26 @@ test("decodes the shared authentication diagnostics on static validation and liv
authentication,
});
});
test.each([
["ready with error", { ready: true, mode: "oidc", checks: [{ level: "error", code: "oidc_secret_missing", message: "failure" }] }],
["failed with ready", { ready: false, mode: "oidc", checks: [{ level: "info", code: "auth_ready", message: "ready" }] }],
["failed without error", { ready: false, mode: "oidc", checks: [{ level: "info", code: "auth_config_invalid", message: "info" }] }],
["duplicate", { ready: false, mode: "oidc", checks: [
{ level: "error", code: "oidc_secret_missing", message: "one" },
{ level: "error", code: "oidc_secret_missing", message: "two" },
] }],
["attacker field", { ready: false, mode: "oidc", checks: [{ level: "error", code: "oidc_secret_missing", message: "failure", field: "attacker-field-SENTINEL" }] }],
["control", { ready: false, mode: "oidc", checks: [{ level: "error", code: "oidc_mapped_group_missing", message: "failure", field: "bad\u0085field" }] }],
["unexpected property", { ready: false, mode: "oidc", checks: [{ level: "error", code: "oidc_secret_missing", message: "failure", attacker: "field" }] }],
])("rejects hostile authentication diagnostics: %s", async (_name, authentication) => {
server.use(http.post("/api/workspaces/validate", () => HttpResponse.json({
workspace,
contract: {},
activatable: false,
diagnostics: [],
authentication,
})));
await expect(validateWorkspace(workspace)).rejects.toThrow("invalid authentication diagnostics");
});
+27 -5
View File
@@ -225,21 +225,36 @@ const authDiagnosticCodes = new Set<AuthDiagnosticCode>([
]);
function text(value: unknown): value is string {
return typeof value === "string" && value.length > 0 && value.length <= 512 && !/[\u0000-\u001f\u007f]/.test(value);
return typeof value === "string" && value.length > 0 && value.length <= 512
&& value.trim() === value && !/\p{Cc}/u.test(value);
}
function decodeAuthentication(value: unknown): AuthDiagnostics {
const source = object(value);
const source = exactObject(value, ["ready", "mode", "checks"]);
if (!source || typeof source.ready !== "boolean"
|| !["local", "oidc", "upstream", "none", "mock"].includes(String(source.mode))
|| !Array.isArray(source.checks)) throw new Error("Workspace API returned invalid authentication diagnostics");
|| typeof source.mode !== "string"
|| !["local", "oidc", "upstream", "none", "mock"].includes(source.mode)
|| !Array.isArray(source.checks) || source.checks.length === 0 || source.checks.length > 129) {
throw new Error("Workspace API returned invalid authentication diagnostics");
}
const seen = new Set<string>();
const checks = source.checks.map((item): AuthDiagnostic => {
const check = object(item);
const raw = object(item);
const check = raw && exactObject(raw, raw.field === undefined
? ["level", "code", "message"]
: ["level", "code", "message", "field"]);
if (!check || (check.level !== "error" && check.level !== "info")
|| typeof check.code !== "string" || !authDiagnosticCodes.has(check.code as AuthDiagnosticCode)
|| !text(check.message) || (check.field !== undefined && !text(check.field))) {
throw new Error("Workspace API returned invalid authentication diagnostics");
}
if (check.field !== undefined
&& check.code !== "oidc_mapped_group_missing" && check.code !== "oidc_mapped_group_ambiguous") {
throw new Error("Workspace API returned invalid authentication diagnostics");
}
const key = `${check.code}\u0000${check.field ?? ""}`;
if (seen.has(key)) throw new Error("Workspace API returned invalid authentication diagnostics");
seen.add(key);
return {
level: check.level,
code: check.code as AuthDiagnosticCode,
@@ -247,6 +262,13 @@ function decodeAuthentication(value: unknown): AuthDiagnostics {
...(check.field === undefined ? {} : { field: check.field }),
};
});
if (source.ready) {
if (checks.length !== 1 || checks[0].level !== "info" || checks[0].code !== "auth_ready"
|| checks[0].field !== undefined) throw new Error("Workspace API returned invalid authentication diagnostics");
} else if (!checks.some(({ level }) => level === "error")
|| checks.some(({ code }) => code === "auth_ready")) {
throw new Error("Workspace API returned invalid authentication diagnostics");
}
return { ready: source.ready, mode: source.mode as AuthDiagnostics["mode"], checks };
}