fix(security): sanitize session bootstrap failures

This commit is contained in:
User
2026-07-14 23:13:21 +02:00
parent f58b1d84ae
commit d2d8029ff2
4 changed files with 62 additions and 10 deletions
+48
View File
@@ -471,3 +471,51 @@ test("POST /sessions returns after bridge attachment but starts only after retri
await new Promise((resolve) => setImmediate(resolve));
expect(started).toBe(true);
});
test("POST /sessions bootstrap failure emits only a fixed recovery message", async () => {
const published: Array<{ event: string; data: any }> = [];
let listener: ((event: any) => void) | undefined;
const bridge = {
onClientEvent: (callback: (event: any) => void) => { listener = callback; },
emitClientEvent: (event: any) => listener?.(event),
};
const runtime = { bridge } as any;
const rawFailure =
"connect https://secret.invalid/bootstrap?token=DO_NOT_LEAK using /srv/private/model-key";
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
mgr: {
createFor: () => runtime,
configure: async () => { throw new Error(rawFailure); },
start: () => {},
teardown: () => {},
} as any,
hub: {
publish: (_id: string, event: string, data: any) => published.push({ event, data }),
} as any,
thtRunner: {
ollamaEnsure: async () => ({ ok: true }),
sessionNew: async () => ({ id: "s-bootstrap" }),
searchPack: async () => {},
failSession: async () => {},
} as any,
getSettings: () => ({ workspace: "psd" }) as any,
});
const response = await app.inject({
method: "POST",
url: "/sessions",
payload: { question: "q" },
});
await new Promise((resolve) => setImmediate(resolve));
expect(response.json()).toEqual({ id: "s-bootstrap" });
expect(published.map(({ data }) => data)).toContainEqual({
type: "info",
level: "error",
text: "Session startup failed. Check configuration and connectivity, then Resume the session.",
});
const clientOutput = JSON.stringify(published);
expect(clientOutput).not.toContain("secret.invalid");
expect(clientOutput).not.toContain("DO_NOT_LEAK");
expect(clientOutput).not.toContain("/srv/private/model-key");
});