You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds learning mode to the macOS Seatbelt backend, following the approved spec (#1609). MXC records what a workload tried to do that the policy blocked, and writes a report in the same format as Windows processContainer.captureDenials. Replaces #1580.
Config:seatbelt.captureDenials { mode, outputPath, retainEtl }, in the 1.1.0-alpha contract only. 1.0.0 rejects it. Schema and Node wire types regenerated.
Modes:block keeps blocked accesses blocked and records them. allow permits default-denied accesses and records them; explicit denies (deniedPaths, ui) still apply.
How it works: MXC tags its profile's deny rules with a per-run ID and reads matching entries from log stream. A start marker confirms log stream is receiving before the workload runs; an end marker confirms late events arrived. A small watchdog stops log stream if MXC is killed.
Repeats: denials are analyzed as they arrive and repeats are counted, so a noisy workload can't push other denials out of the report.
retainEtl: keeps the raw log stream output as an owner-only .seatbelt.log, reported in etlPath. Capped at 1 GiB with a warning.
Warnings: incomplete captures and trace truncation surface as process warnings, including through the SDK streaming path.
Discovery: Seatbelt advertises captureDenials when /usr/bin/log is available.
mxc-exec-mac --audit: shortcut for allow-mode capture to a temp file.
Rejected:captureDenials with profileOverride.
Docs: Seatbelt guide learning-mode section, schema.md. logging-access-denied.md renamed to learning-mode.md. A new "Required V2 changes" section in versioning.md.
Limitations (documented):
macOS hides remote addresses in network reports (port only).
Reads of missing paths aren't reported.
The typed .NET/Node/Rust SDK fields wait until contract 1.1.0 is published (spec step 5); until then, use the V1.Dev JSON entry points.
🔗 References
Resolves#1591. After this PR, open a follow up for spec steps 4/5.
cargo test -p mxc-sdk --test mxc_contract_v1_1_0_alpha: passed (380)
cargo test -p mxc-sdk --test mxc_contract_v1_0_0: passed (281)
cargo test -p mxc-sdk --test streaming: passed (23). seatbelt_pty_preserves_explicit_timeout_kill fails about 1 run in 6 here and on main; not caused by this PR.
tests/scripts/run_seatbelt_capture_denials_test.sh: passed (99 assertions). New functional suite, wired into the nightly macOS Seatbelt validation through run_seatbelt_all_tests.sh.
Adds learning mode to MXC’s macOS Seatbelt backend, using the shared Windows denial-report format. Configuration is limited to 1.1.0-alpha; typed SDK support remains deferred until contract publication.
Changes:
Adds block/allow capture, retained traces, capability discovery, and the --audit shortcut.
Shares report-writing helpers and propagates capture warnings and teardown errors.
Adds contract and functional coverage, nightly-suite integration, and usage documentation.
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not add it. I optimized how MXC stores repeated denials in memory, so memory grows only with unique denials and verbose groups. Denials are capped at 10,000 entries, like Windows. Each holds one path, and macOS only reports paths up to about 1 KB. A test with a 3 KB path reported at most 824 bytes. That puts the worst case around 20 MiB, so a 16 MiB budget would rarely trigger.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Capture tagging can mistake (deny inside a newline-containing path for a rule, corrupting the generated Seatbelt profile and preventing the workload from starting.
[P2] This line-based pass also matches (deny inside quoted path literals: a path containing secret\n(deny data) keeps its newline through quote_scheme, so the inserted modifier adds unescaped quotes inside the subpath string. Enabling capture then corrupts the generated profile and prevents the workload from starting. Add tags while emitting deny rules, or make this pass respect Scheme string boundaries, and add a regression scenario with a newline-containing path.
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
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.
📖 Description
Adds learning mode to the macOS Seatbelt backend, following the approved spec (#1609). MXC records what a workload tried to do that the policy blocked, and writes a report in the same format as Windows
processContainer.captureDenials. Replaces #1580.seatbelt.captureDenials { mode, outputPath, retainEtl }, in the1.1.0-alphacontract only.1.0.0rejects it. Schema and Node wire types regenerated.blockkeeps blocked accesses blocked and records them.allowpermits default-denied accesses and records them; explicit denies (deniedPaths,ui) still apply.log stream. A start marker confirmslog streamis receiving before the workload runs; an end marker confirms late events arrived. A small watchdog stopslog streamif MXC is killed.retainEtl: keeps the rawlog streamoutput as an owner-only.seatbelt.log, reported inetlPath. Capped at 1 GiB with a warning.captureDenialswhen/usr/bin/logis available.mxc-exec-mac --audit: shortcut for allow-mode capture to a temp file.captureDenialswithprofileOverride.schema.md.logging-access-denied.mdrenamed tolearning-mode.md. A new "Required V2 changes" section inversioning.md.Limitations (documented):
1.1.0is published (spec step 5); until then, use theV1.DevJSON entry points.🔗 References
Resolves #1591. After this PR, open a follow up for spec steps 4/5.
🔍 Validation
Run on macOS (Apple Silicon):
cargo fmt --all -- --check: passedcargo clippy -p mxc-sdk -p mxc_darwin --all-targets -- -D warnings: passedcargo clippy -p mxc-sdk --lib --tests --target x86_64-unknown-linux-gnu -- -D warnings: passedcargo clippy -p mxc-sdk --lib --tests --target x86_64-pc-windows-msvc -- -D warnings: passedcargo test -p mxc-sdk --lib: passed (1913)cargo test -p mxc-sdk --test mxc_contract_v1_1_0_alpha: passed (380)cargo test -p mxc-sdk --test mxc_contract_v1_0_0: passed (281)cargo test -p mxc-sdk --test streaming: passed (23).seatbelt_pty_preserves_explicit_timeout_killfails about 1 run in 6 here and onmain; not caused by this PR.node scripts/versioning/check-contract-codegen.js: passednode scripts/versioning/validate-configs.js: passedtests/scripts/run_seatbelt_capture_denials_test.sh: passed (99 assertions). New functional suite, wired into the nightly macOS Seatbelt validation throughrun_seatbelt_all_tests.sh.tests/scripts/run_seatbelt_all_tests.sh: passed (16/16)✅ Checklist
feature-acceptedCargo.lock, thedependency-feed-checkcheck passes (see pull request builds)📋 Issue Type