fix(security): audit fixes — path traversal, race conditions, memory leaks, transaction safety

- lib.rs: claude_read_skill path traversal prevention (canonicalize + starts_with)
- agent-dispatcher.ts: re-entrancy guard on exit handler, clear maps in stop
- machines.svelte.ts: track UnlistenFn array + destroyMachineListeners()
- agent-runner.ts: controller.signal.aborted, async handleMessage + .catch()
- remote.rs: try_lock → async lock, abort tasks on remove
- session.rs: unchecked_transaction for save_agent_messages
- agent-bridge.ts: safe msg.event check (implicit in dispatcher changes)
This commit is contained in:
Hibryda 2026-03-08 20:03:50 +01:00
parent 73ca780b54
commit 4bdb74721d
6 changed files with 102 additions and 57 deletions

View file

@ -26,7 +26,9 @@ function log(message: string) {
rl.on('line', (line: string) => {
try {
const msg = JSON.parse(line);
handleMessage(msg);
handleMessage(msg).catch((err: unknown) => {
log(`Unhandled error in message handler: ${err}`);
});
} catch {
log(`Invalid JSON: ${line}`);
}
@ -53,13 +55,13 @@ interface StopMessage {
sessionId: string;
}
function handleMessage(msg: Record<string, unknown>) {
async function handleMessage(msg: Record<string, unknown>) {
switch (msg.type) {
case 'ping':
send({ type: 'pong' });
break;
case 'query':
handleQuery(msg as unknown as QueryMessage);
await handleQuery(msg as unknown as QueryMessage);
break;
case 'stop':
handleStop(msg as unknown as StopMessage);
@ -149,7 +151,7 @@ async function handleQuery(msg: QueryMessage) {
sessions.delete(sessionId);
const errMsg = err instanceof Error ? err.message : String(err);
if (errMsg.includes('aborted') || errMsg.includes('AbortError')) {
if (controller.signal.aborted) {
log(`Agent session ${sessionId} aborted`);
send({
type: 'agent_stopped',