26454ed98d54

runHook quotes $1 in its sh -c runner script so a hook path containing spaces or glob characters runs correctly (NINA-010)

time
2026-07-02 13:26 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
fable audit fix — exec.zig
parent
d4dd5ae4eb6e
1 file src/exec.zig+20 −1
src/exec.zig+20 −1
@@ -224,7 +224,7 @@224224         .argv = &.{225225             "sh",226226             "-c",227-            "$1 > \"$2\" 2>&1; code=$?; tail -c 4096 \"$2\"; exit \"$code\"",227+            "\"$1\" > \"$2\" 2>&1; code=$?; tail -c 4096 \"$2\"; exit \"$code\"",228228             "nina-hook-run",229229             hook_path,230230             tmp_output,@@ -289,6 +289,25 @@289289     try std.testing.expectEqual(@as(u8, 3), failed.exit_code);290290     try std.testing.expect(std.mem.indexOf(u8, failed.output, "hook says no") != null);291291     try std.testing.expect(std.mem.indexOf(u8, failed.output, "detail") != null);292+293+    // NINA-010: the runner script's `$1` (the hook path) must be quoted — a294+    // hook whose path contains a space used to word-split and fail to run.295+    const spaced_script =296+        \\#!/bin/sh297+        \\echo spaced hook ran298+        \\exit 0299+        \\300+    ;301+    {302+        const file = try hook_dir.createFile(io, "post apply", .{});303+        defer file.close(io);304+        try file.writePositionalAll(io, spaced_script, 0);305+        try file.setPermissions(io, .fromMode(0o755));306+    }307+    const spaced = try runHook(a, io, &env, "post apply");308+    defer a.free(spaced.output);309+    try std.testing.expectEqual(HookResult.ok, spaced.result);310+    try std.testing.expect(std.mem.indexOf(u8, spaced.output, "spaced hook ran") != null);292311 }293312 294313 // Single-quote-wrap `arg` for a POSIX shell, escaping embedded single quotes as

view file