Skip to content

Commit d709225

Browse files
committed
fix(isolation): address containment review gates
1 parent 66b87bd commit d709225

3 files changed

Lines changed: 21 additions & 17 deletions

File tree

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Operational rules and references for automated agents working on this repo. Inst
2424
npm version or GitHub Release.
2525
- Provider output-silence liveness checks are opt-in (`enableLivenessCheck: true`). Recovery tests
2626
that exercise stale-agent termination must enable the watchdog explicitly.
27+
- Isolation copies must reuse the shared pinned-root boundary in `src/copy-containment.js` for
28+
traversal, directory creation, synchronous copies, and worker copies. Revalidate the source and
29+
destination immediately before every filesystem effect; never reconstruct unchecked effect paths.
2730

2831
Worker git operations are allowed only with isolation (`--worktree`, `--docker`, `--pr`, `--ship`). They are forbidden without isolation.
2932

CLAUDE.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ Message-passing primitives for multi-agent workflows. **Install:** `npm i -g @th
66

77
## 🔴 CRITICAL RULES
88

9-
| Rule | Why | Forbidden | Required |
10-
| ---------------------------------- | ---------------------------- | -------------------------------------------- | ------------------------------------------------ |
11-
| **GENERAL PURPOSE ONLY** | Zeroshot runs on ANY repo | Hardcoded paths, scripts, languages, domains | Discover from target repo's CLAUDE.md/README |
12-
| **Never spawn without permission** | Consumes API credits | "I'll run zeroshot on 123" | User says "run zeroshot" |
13-
| **Never use git in validators** | Git state unreliable | `git diff`, `git status` in prompts | Validate files directly |
14-
| **Never ask questions** | Agents run non-interactively | `AskUserQuestion`, waiting for confirmation | Make autonomous decisions |
15-
| **Never edit CLAUDE.md** | Context file for Claude Code | Editing this file | Read-only unless explicitly asked to update docs |
9+
| Rule | Why | Forbidden | Required |
10+
| ---------------------------------- | --------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------- |
11+
| **GENERAL PURPOSE ONLY** | Zeroshot runs on ANY repo | Hardcoded paths, scripts, languages, domains | Discover from target repo's CLAUDE.md/README |
12+
| **Never spawn without permission** | Consumes API credits | "I'll run zeroshot on 123" | User says "run zeroshot" |
13+
| **Never use git in validators** | Git state unreliable | `git diff`, `git status` in prompts | Validate files directly |
14+
| **Never ask questions** | Agents run non-interactively | `AskUserQuestion`, waiting for confirmation | Make autonomous decisions |
15+
| **Never edit CLAUDE.md** | Context file for Claude Code | Editing this file | Read-only unless explicitly asked to update docs |
16+
| **Preserve copy containment** | Copy paths cross trust boundaries | Independent path joins or one-time checks | Reuse the pinned-root boundary and revalidate immediately before every filesystem effect |
1617

1718
### 🔴 GENERAL PURPOSE REQUIREMENT (CRITICAL)
1819

tests/isolation-copy-containment.test.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const assert = require('assert');
2-
const fs = require('fs');
3-
const os = require('os');
4-
const path = require('path');
1+
const assert = require('node:assert');
2+
const fs = require('node:fs');
3+
const os = require('node:os');
4+
const path = require('node:path');
55

66
const IsolationManager = require('../src/isolation-manager');
77
const {
@@ -23,14 +23,14 @@ function isContainmentError(error) {
2323
}
2424

2525
async function captureContainmentError(copyPromise) {
26-
try {
27-
await copyPromise;
28-
assert.fail('expected copy containment to reject');
29-
} catch (error) {
26+
let containmentError;
27+
await assert.rejects(copyPromise, (error) => {
3028
assert.ok(error instanceof CopyContainmentError, error.stack || error.message);
3129
assert.strictEqual(isContainmentError(error), true);
32-
return error;
33-
}
30+
containmentError = error;
31+
return true;
32+
});
33+
return containmentError;
3434
}
3535

3636
describe('isolation copy containment', function () {

0 commit comments

Comments
 (0)