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.
We use
SandboxManager.initialize(config, callback, enableLogMonitor=true)andSandboxViolationStoreto 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/openonly trap intoSECCOMP_RET_USER_NOTIFwhen the syscall's flags includeOBS_WRITE_MASK(O_WRONLY|O_RDWR|O_CREAT|O_TRUNC|O_APPEND). A plainO_RDONLYopen never reaches the trap, so adenyRead-blocked read is invisible toSandboxViolationStore, even though bwrap correctly enforces the deny and the process gets EACCES/EPERM.LinuxViolationMonitorOptionsalso has noallowReadPaths/denyReadPaths, so this looks structurally out of scope for the current design, not just unwired.Practically: with a restrictive
denyReadposture (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 readingSandboxViolationStore. 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 toallowWritePaths/denyWritePathsbefore 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.