[FEATURE] Mods API: let a tool.call hook add file deny rules to one Bash call's sandbox
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Arrester (github.com/dot-agi/arrester) is a mod that keeps a blocked target blocked. After a hook, a deny rule or auto mode refuses a tool call, it stops later calls that reach the same file another way, such as head after a blocked cat. Claude Code 2.1.296, macOS.
For Bash, the mod can only read the command text before it runs. A static scan cannot see paths that the shell computes at run time, user functions, aliases, or code inside interpreters and compiled programs. So a later Bash call can still read or change the blocked file.
The OS sandbox already enforces file rules for every process a Bash call starts. A mod cannot use it:
$.settings.readis read-only:read: (args?: SettingsReadArgs) => Promise<Settings>;- The
tool.callinput for Bash is the model's input. A hook can rewrite it, but it holds no sandbox rules, onlydangerouslyDisableSandbox?: boolean.
Proposed Solution
Let a tool.call hook add sandbox file rules that apply to this one Bash call only:
// on a Bash tool.call, passed on with next(e)
requestMeta?: {
sandbox?: {
denyRead?: readonly string[]; // absolute paths or globs
denyWrite?: readonly string[];
};
};
- The rules only narrow the session's sandbox. They never widen it.
- If a hook adds rules, the call cannot run unsandboxed:
dangerouslyDisableSandboxis refused for it, with a reason the model sees. - When the sandbox is off for the session, the engine tells the hook that the rules cannot apply, so the mod can fall back to its own check.
Alternative Solutions
A full shell parser in the mod would still miss computed paths and compiled programs. Writing sandbox rules into the user's settings would change other sessions and leave rules behind.
Priority
Medium - Would be very helpful
Feature Category
Developer tools/SDK
Use Case Example
- A hook denies
cat secrets/prod.env. Arrester opens a block on that file. - Claude runs
python3 -c "open(os.environ['F']).read()"withFset elsewhere. - Arrester adds
denyRead: ['/repo/secrets/prod.env']to that Bash call. The sandbox refuses the read, whatever the code computes.
This would close Arrester's "Interpreter code scan is shallow" and "Aliases, functions and unlisted runners" known limits.
Additional Context
Quotes are from the generated 2.1.296 mod types (claude-code/index.d.ts, $.settings.read; claude-code-tools/index.d.ts, the Bash input).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗