SPB Git

spb/autoscholar

Public

Policy: deny nested .claude/.git/.ssh/.aws/.config paths in the workspace

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Oct 30, 2026) parent 5ba599e Browse files

2 changed files +5 −3

modified services/research-runner/src/policy.test.ts +2 −0
@@ -77,6 +77,8 @@ describe("platform policy hook", () => {
77 77 expect(isDeny(await call("Edit", { file_path: join(ws, "CLAUDE.md") }))).toBe(true);
78 78 expect(isDeny(await call("Write", { file_path: join(ws, "input/run.json") }))).toBe(true);
79 79 expect(isDeny(await call("Write", { file_path: join(ws, ".claude/settings.json") }))).toBe(true);
80 + expect(isDeny(await call("Write", { file_path: join(ws, "code/.claude/settings.json") }))).toBe(true);
81 + expect(isDeny(await call("Write", { file_path: join(ws, "code/.git/hooks/pre-commit") }))).toBe(true);
80 82 expect(isDeny(await call("Write", { file_path: join(ws, "results/link/evil.txt") }))).toBe(true); // symlink to outside
81 83 });
82 84 it("reviewer sessions may only write under review/", async () => {
modified services/research-runner/src/policy.ts +3 −3
@@ -202,10 +202,10 @@ export function createPolicyHook(opts: PolicyOptions): HookCallback {
202 202 const rel = relativeInWorkspace(opts.workspace, p);
203 203 if (rel === null) return deny(input, "write outside the run workspace", { path: p });
204 204 if (
205 − rel.startsWith(".claude/") ||
206 − rel === ".claude" ||
205 + rel.split("/").includes(".claude") ||
207 206 rel.startsWith(".autoscholar/") ||
208 − rel.startsWith("home/")
207 + rel.startsWith("home/") ||
208 + rel.split("/").some((seg) => [".git", ".ssh", ".aws", ".config"].includes(seg))
209 209 )
210 210 return deny(input, "platform-reserved directory", { path: rel });
211 211 for (const f of opts.frozenPaths)
212 212
Menu

Theme