Repository navigation
feat(sandbox): emit OCSF File System Activity for audited paths - #5144
Open
vineethsai7 wants to merge 7 commits into
Open
vineethsai7 wants to merge 7 commits into
vineethsai7 wants to merge 7 commits into
Conversation
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Author
|
I have read the DCO document and I hereby sign the DCO. |
8 of 9 tasks
vineethsai7
marked this pull request as ready for review
November 3, 2026 04:50
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
3 of 6 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #5143. The first 2 commits are from #5143; review only 155c68a..6efb317.
Summary
Add opt-in File System Activity events for opens of policy-named paths. This is a first slice of filesystem auditing: it reports an observed open attempt without claiming the kernel allowed or denied it.
Related Issue
Part of #4270. The issue is still
state:triage-needed; this is a draft design and maintainer feedback is welcome.Changes
filesystem_policy.audit_pathsto authored policy, gateway protobuf, and the sandbox attach protocol. Empty lists preserve existing behavior.AuditPathsthrough the Go SDK policy type, converters, and fake client.open,openat, andopenat2requests in the built-in sandbox boundary's existing seccomp notification broker. Bound the output to 100 matching events per second per sandbox and emit a counted drop record for suppressed matches.audit_pathsin the MXC policy mapper, which has no Linux open listener./app/agent.pyfirst-run case raised in the issue comments.Design
The built-in boundary already receives open notifications for provider files. It reads the full requested path only when
audit_pathsis nonempty, matches that text against validated globs, emits an OCSF event, then lets the existing provider-file handler continue. This keeps the default prefix fast path and uses the same boundary in Docker, Podman, Kubernetes, and the MicroVM guest.The notification arrives before the kernel completes the syscall. After
SECCOMP_USER_NOTIF_FLAG_CONTINUE, the broker cannot see the subsequent Landlock result, so this slice emitsObservedand leaves disposition and status unset. ReportingAllowedorDeniedhere would assert a result the broker does not know. The requested path is labeledsyscall_argument; relative paths, directory file descriptors, and symlinks are not resolved for matching.Alternatives considered
Release Notes
Create a sandbox with absolute watch globs to log matching file open attempts. An empty list, the default, emits no file activity events. Watch-list changes require recreating the sandbox.
Example
policy.yaml:The workload container log contains shorthand like:
The corresponding OCSF event has these fields (common metadata omitted):
{ "class_uid": 1001, "activity_id": 14, "action_id": 3, "file": {"name": ".env", "path": "/sandbox/project/.env", "type_id": 0}, "actor": {"process": {"name": "python3", "path": "/usr/bin/python3", "pid": 42}}, "unmapped": { "requested_path": "/sandbox/project/.env", "path_source": "syscall_argument", "access_type": "read" } }action_id: 3means Observed. A suppressed-event summary is a Base Event withunmapped.dropped_countandunmapped.reason: rate_limit. Runtime-originated events currently appear in workload container logs, not the supervisor JSONL file or gateway log stream.Compatibility
audit_pathsdefaults to an empty list and is omitted from the JSON boundary wire form when empty. The protobuf additions use new field numbers. Existing policies and attach clients retain their previous behavior. A nonempty watch list adds full path reads to open notifications and has a per-sandbox output cap. The watch list is bound before workload launch; live changes are rejected.The MXC driver rejects a nonempty watch list at sandbox creation instead of silently dropping it.
Review follow-up
audit_pathsin the MXC policy mapper. MXC has no Linux boundary open listener, so accepting the list would leave an enabled audit policy without file events. The mapper reports an error before sandbox creation; the regression covers both MXC mapping paths.Timestamp; this branch merges that commit without duplicating the protocol fields.Testing
clippy --all-targets -- -D warningson affected Rust crates; affected Rust unit suites and live seccomp integration test; Go SDK tests andgofmt; pinned protobuf regeneration andbuf lint; docs navigation and Markdown lint; Fern check (zero errors, three warnings in untouched content); locked metadata for both affected example workspaces.cargo fmt --all -- --check, clippy with--all-targets -- -D warnings, and serialcargo testfor all eleven affected Rust crates. The sandbox suite passed 293/293 and the server suite passed 2605/2605.Timestampand passes on the merged head.One existing socket lifecycle test failed during a parallel sandbox suite run on the shared builder; it passed when rerun alone and in the serial sandbox suite. The final serial sandbox suite passed 293/293. No driver E2E run was available under this task's host restrictions.
Follow-ups
/app/agent.pystartup denial from the issue comments remains undiagnosed by an event in this slice.Checklist
Manual verification
Result: PASS — On the same ARM64 stack host, upstream main rejected
filesystem_policy.audit_pathsand emitted no file event for a broker-mediated open. PR head accepted the watch list and emitted one OCSF File System Activity event for the watched open, withObservedaction and no asserted outcome. Clearing the watch list stopped further file events.Environment
dc-ubuntu-eh), kernel7.0.0-1014-aws. Runs used one disposable unprivileged account with a private HOME. The host has no Docker or Podman, so this is a live seccomp-broker proof, not a driver end-to-end run. No existing service or default port was changed.cc0642fa8955be9db480937193693968ada92a49. After: PR head6efb3176d5cc7d5520c5b8fe3aac6eec7d2e7262. Both release test binaries were cross-built throughdcb up-os-4270withnice -n 15 cargo build --release --target aarch64-unknown-linux-musl -p openshell-sandbox --tests, Zig 0.14.0 as linker, andRUSTFLAGS='-C link-self-contained=no'. Main built with--locked; PR head required an unlocked build because itsCargo.lockomits the newopenshell-ocsfdependency ofopenshell-sandbox-backend(the unlocked build added just that lock entry). Temporary probe assertions and two ARM64 test-only libc portability adjustments were removed after the run; the checked-out PR worktree is clean.Steps
openshell-sandboxtest binary with the command above and copy it to the disposable account on the stack host.network_broker::tests::proof_5144_before_open_has_no_file_activityand the PR testnetwork_broker::tests::watched_open_emits_observed_file_activity_and_continues, each with--exact --nocapture --test-threads=1.audit_pathspolicy. The PR probe parses a policy naming the temporary watched file, opens watched and unwatched files, checks the captured OCSF event, clears the watch list, and opens the watched file again.Before: upstream main
The file read succeeded, but main rejected the audit policy and emitted no File System Activity event:
After: PR head
The watched read succeeded. Exactly one matching event had
class_uid=1001, Openactivity_id=14, Observedaction_id=3, the requested file path, read access, a process PID, and no status or disposition. The unwatched open emitted no file event. After configuring an empty watch list, reopening the watched file emitted no new event:Not covered
Cleanup
The disposable account, private HOME, and staging directory were deleted. Readback found zero identity entries, proof processes, or proof listeners, and no proof HOME or staging directory. The dev and build worktrees were restored to the PR head without a commit or push.