Skip to content

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

Description

@karljamoralin

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions