Repository navigation
Conversation
render_profile emitted the deny_read block as the profile's last rule, so it overrode every write grant. The native shell adds its per-call scratch (TMPDIR) to read_write after admission, so a host that denied the folder holding its state directory, such as ~/.openhuman, left every jailed command without a usable TMPDIR. After the deny block, re-allow reads and writes for each writable grant that sits strictly inside a denied path. Seatbelt applies the last matching rule, which a macOS probe confirmed: an allow after a deny re-opens the subpath and leaves the rest denied. Admission already refuses a host's writable grant under a denial, so in practice this carves out only the scratch. Refs tinyhumansai#89
deny_read takes exact paths, so a host could not deny a credential file name wherever it appears, such as a project's .npmrc (tinyhumansai#89). - NativeJailConfig gains deny_read_names (contract 2.5, empty and omitted by default): one path component each, validated at admission and counted against MAX_NATIVE_JAIL_GRANTS. - JailBackend gains denies_by_name (default false). Seatbelt returns true and renders each name as a regex deny of /<name> and everything below it, as the profile's last rule, after the scratch carve-out. A macOS probe confirmed sandbox-exec honours a regex denial at any depth. - Every other backend refuses such a jail instead of ignoring it, both in the module's admission (with the reason) and in the tinybox_jail spawn helpers. - NativeJailConfig gets a most-restrictive Default, so a host building requests with ..NativeJailConfig::default() keeps compiling when the contract grows a field. Every literal in this workspace gains the new field. Closes tinyhumansai#89
ResourceLimits.disk_bytes was a required u64 defaulting to 8 GiB, and an explicit native jail budget turned it into a hard Disk requirement that no backend enforces, so every legacy jail request with resources was refused. disk_bytes is now Option<u64>, absent by default and on the wire when unset. A native jail requires Disk only when the caller sets one; a box keeps the soft core default. Contract 2.6, since a module before it cannot decode a budget without the field.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Tiny Sweeper reviewReviewed head: Verdict: Ready for maintainer review · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): Make a resource budget's disk limit optional (contract 2.6). Under contract 2.6, `ResourceLimits::disk_bytes` becomes `Option<u64>` (default `None`, omitted on the wire), so a native jail asks for `Disk` only when a caller set one; an explicit CPU/memory/pids budget without a disk value now reaches backends able to hold those three constraints instead of being refused for a disk limit nothing enforces. `Create` keeps the soft core `Resources::DEFAULT.disk_bytes` when the field is unset, and the contract version moves to (2,6), which is what makes the omission decodable only against a 2.6 module. The diff also carries the stacked 2.5 `deny_read_names` work, which the description says to review separately. Review snapshot
Completeness: Complete What changed25 files changed, 567 additions, 32 deletions. `ResourceLimits::disk_bytes` becomes `Option<u64>` with `None` default and `skip_serializing_if`; `CONTRACT_VERSION` becomes (2,6); native jail `required_resource_constraints` adds `Disk` only when `disk_bytes` is `Some`; `make_spec` and `configure_resources` fall back to `Resources::DEFAULT.disk_bytes` when unset; version tests pin (2,6) and reject (2,4)/(2,5); new `docs/specs/contract-2-6.md`; new tests for the wire shape, the disk-constraint gating, and the soft core default. The stacked 2.5 material (`deny_read_names`, `NativeJailConfig::default()`, Seatbelt carve-out and name-denial regex, boxed `ShellHost::Jailed`) is also present. Features
Tests
FindingsNo active actionable findings. Before mergeNone. How this fits togetherflowchart LR
n0["NativeJailConfig<br/>changed"]:::changed
n1["...ubset_is_additive_and_keeps_disk_explicit<br/>changed"]:::changed
n2["..._limits_are_optional_typed_and_round_trip<br/>changed"]:::changed
n3["ResourceLimits<br/>changed"]:::changed
n0 -->|uses| n3
n1 -->|uses| n0
n2 -->|uses| n0
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
# Conflicts: # crates/tinybox-module/src/tinybus_module/native_jail_tests.rs
Summary
ResourceLimits.disk_byteswas a requiredu64defaulting to 8 GiB. No backend enforces a writable disk budget, so onCreatethe value was never applied. On a native jail, an explicitresourcesbudget made all four fields hard requirements, Disk included, and every backend refused. So everyStartJailedExecrequest carrying resources was refused, whatever its CPU, memory and pids.Contract 2.6 makes
disk_bytesanOption<u64>:Noneby default, and omitted on the wire whenNone.disk_bytesis set, so a CPU/memory/pids budget is judged on what it asks for.Stacked on #158 (contract 2.5); review only the last commit.
Related issue
Part of #27 (enforcement gaps: the mandatory disk budget).
API or behavior changes
tinybox_bus::ResourceLimits::disk_byteschanges fromu64toOption<u64>, andResourceLimits::default()now hasNone. This is source-breaking for code that builds the struct literally or reads the field.CONTRACT_VERSION= (2, 6).ResourceLimitswithoutdisk_bytes. A host must have bound a 2.6 module, whichis_compatiblealready requires of a 2.6 host, before it sends one. A host built on 2.6 that talks to older modules must keep settingdisk_bytes.disk_bytesis no longer refused for Disk. It is still refused by any backend that cannot enforce CPU, memory and pids.Resourcesand stored box records are unchanged.Validation
On our Linux CI runner, at 121446c7a9. The head is the same commit rebased onto #158's final formatting fix, and
cargo fmt --checkon the head is clean:cargo clippy --all-targets --all-features -- -D warnings: 0 errors, same as main.cargo build --all-targets --all-featuresandRUSTDOCFLAGS="-D warnings" cargo doc: ok.cargo test --locked --all-features --workspace --no-fail-fast: 1589 passed, 0 failed, with no failures unique to this branch (main: 1575 passed). The version tests pin (2, 6).a_native_jail_budget_requires_disk_only_when_one_is_set;disk_bytes_is_optional_and_absent_by_default, becauseNonethen serializes asnull.Tests
disk_bytes_is_optional_and_absent_by_default:disk_bytesdecodes asSomeand re-encodes unchanged;None;a_native_jail_budget_requires_disk_only_when_one_is_set: Cpu, Memory and Pids are always required; Disk only when set.an_unset_disk_budget_keeps_the_soft_core_default: aCreatewithout a disk budget keepsResources::DEFAULT.disk_bytesand adds no hard requirement.Documentation
docs/specs/contract-2-6.md, the contract version doc intinybox-bus/src/lib.rs, and rustdoc on the field.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the description