b58791644839ad45c697f03f125b987cea58df10

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Allow shell syntax checks

Diff

 1diff --git a/src/core/rules.ts b/src/core/rules.ts
 2index ddc5f2dc2092efb6dc7e62631a43a980fd5fee88..e9dcdd4291e3e57e2779adb15b14f2304827ac56 100644
 3--- a/src/core/rules.ts
 4+++ b/src/core/rules.ts
 5@@ -1,7 +1,7 @@
 6 import { DECISION_CATEGORIES } from "./types";
 7 
 8 // Bump to invalidate all cached decisions when rules change.
 9-export const POLICY_VERSION = 32;
10+export const POLICY_VERSION = 33;
11 
12 // Trailing stderr redirections that are safe to strip before pattern matching.
13 // `2>&1` and `2>/dev/null` have no security implication but would otherwise
14@@ -79,7 +79,7 @@ export const HARD_ALLOW_PATTERNS: RegExp[] = [
15   /^sleep\s+[\d.]+\s*$/,
16 
17   // `-n` checks syntax only; it never executes the script.
18-  /^(ba)?sh\s+-n(?:\s+(?!.*\/\.)(?!.*\.\.)\S+)+\s*$/,
19+  /^(ba)?sh\s+-n(?:\s+\S+)*\s*$/,
20 ];
21 
22 // Broader prefix patterns ported from the OpenCode config.
23diff --git a/test/core/deterministic.test.ts b/test/core/deterministic.test.ts
24new file mode 100644
25index 0000000000000000000000000000000000000000..08687870ac2ecacc901bba2f7c813aae483c7a07
26--- /dev/null
27+++ b/test/core/deterministic.test.ts
28@@ -0,0 +1,18 @@
29+import { expect, test } from "bun:test"
30+import { checkDeterministic } from "../../src/core/deterministic"
31+
32+test("allows sh syntax checks without restricting the source path", () => {
33+  for (const command of [
34+    "sh -n script.sh",
35+    "sh -n ./script.sh",
36+    "bash -n /tmp/script.sh",
37+    "bash -n ../script.sh",
38+    "bash -n",
39+  ]) {
40+    expect(checkDeterministic("bash", { command })).toMatchObject({ decision: "allow" })
41+  }
42+})
43+
44+test("keeps shell execution subject to confirmation", () => {
45+  expect(checkDeterministic("bash", { command: "bash script.sh -n" })).toMatchObject({ decision: "ask" })
46+})