anthropics / anthropics/sandbox-runtime

Linux violation monitor doesn't observe read-only opens (denyRead blocks are invisible to SandboxViolationStore)

Open
#511 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
5.2k
Forks
439
Avg merge
2d 9m
Merged PRs (30d)
13

Description

We use `SandboxManager.initialize(config, callback, enableLogMonitor=true)` and `SandboxViolationStore` to turn a raw OS permission error into a human-readable "blocked by the sandbox" message for an AI coding agent. This works well on macOS via the Seatbelt log stream, and since #322 (v0.0.65), for Linux write-intent denials via the seccomp USER_NOTIF observer.

Read-only denials on Linux don't produce a violation event at all. Traced it to the BPF filter in `vendor/seccomp-src/apply-seccomp.c`: `openat`/`open` only trap into `SECCOMP_RET_USER_NOTIF` when the syscall's flags include `OBS_WRITE_MASK` (`O_WRONLY|O_RDWR|O_CREAT|O_TRUNC|O_APPEND`). A plain `O_RDONLY` open never reaches the trap, so a `denyRead`-blocked read is invisible to `SandboxViolationStore`, even though bwrap correctly enforces the deny and the process gets EACCES/EPERM. `LinuxViolationMonitorOptions` also has no `allowReadPaths`/`denyReadPaths`, so this looks structurally out of scope for the current design, not just unwired.

Practically: with a restrictive `denyRead` posture (deny-by-default reads, narrow allowlist), a denied read, probably the single most common sandbox block for a coding agent, surfaces a raw "Operation not permitted" with no signal for anything reading `SandboxViolationStore`. That breaks parity with macOS and with Linux's own write-side behavior.

We're guessing this is deliberate. #322's own description says "Read-only opens never trap (the BPF gates on the flags argument), so exec/compile paths are untouched," and trapping every read would hit every exec, shared-library load, and config read, way more volume than writes. We're not asking for "trap all reads."

One direction worth considering: scope read observation to only the paths an embedder has explicitly configured as `denyRead`, the same way the write-observer already narrows to `allowWritePaths`/`denyWritePaths` before deciding whether to report. We don't have visibility into the perf tradeoffs on your side, so this is a starting point for discussion, not a specific ask.

We're not blocked on this. Writes are covered, and reads are still correctly enforced, just not observed. Flagging it because it's a real parity gap.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.