Skip to main content

Module containment

Module containment 

Source
Expand description

Containment classes: what an operator declares versus what a session actually achieves.

The two directions are deliberately kept apart:

  • The declared floor (murmur_artifact::ContainmentClass) is a requirement, combined from the manifest, the workspace config and --containment by taking the strongest (see murmur_artifact::effective_containment_floor).
  • The achieved class is the class of the tier the session’s commands run on. That tier, and the class read off it, are one ContainmentDecision, made once per session from one HostProbe reading and the declared floor. The host’s tier is a ceiling the declaration can only lower: a capsule declaring less than sealed on a sealed-capable host runs on [EnforcementTier::KernelFull] and achieves scoped, and no declaration raises a tier above what the host backs. [achieved_class_for_tier] takes nothing but a tier, so no declaration can talk a tier into reporting a class it does not back. Two capsule-side facts then cap the class at ContainmentClass::Advisory without changing the tier: capabilities.filesystem.workdir_exec: true and a runtime directory inside the workdir (see [achieved_containment_class]).

What the host could back for a capsule declaring sealed is reported separately, as ContainmentDecision::host_containment, and decides nothing.

ContainmentClass::Sealed is reachable exactly when [EnforcementTier::KernelSealed] is applied: a Linux host with a usable Landlock ABI and a namespace probe that really built the composed root inside the capsule’s network namespace, and a capsule declaring sealed. See crate::sealed for the mechanism and for the crate::sealed::SealedBlocker taxonomy that turns “not sealed here” into a specific command an operator can run.

The shortfall reason for sealed is therefore mechanism-specific, not a fixed string: a host missing the AppArmor profile and a container missing CAP_SYS_ADMIN both fail to reach sealed, but they are fixed in completely different places, and a refusal that cannot tell them apart is a refusal an operator cannot act on.

Structs§

ContainmentDecision
A session’s containment, decided once: the tier its commands run on and the class that tier achieves for this capsule.
DeclaredNeedsReport
One element of ScopeReport::declared_needs: what one artifact’s needs for one program resolved to. Every key is always serialized.
DoctorDirReports
What doctor_runtime_dir reports.
ExportsFilesReport
The declared exports.files block as it appears in a ScopeReport — and therefore in mur run --explain-scope --json and in trace.jsonl’s session_start.effective_grants.
ExtraRootReport
One extra root as PreopenReport::extra_roots carries it. Every key is always present.
FilesystemBoundaryReport
What the filesystem mechanism this session installs does not protect, in words an operator can act on.
GrantedNeedReport
A granted need: its label (library libm.so.6, program_folder .) and each path, rendered <path> for a file and <path> (list_dir) for a directory.
ImagesReport
The Images block of the scope report: the limits on images a tool returns or an A2A message carries.
MissingNeedReport
A missing need: its label and why it is not granted.
PeerFilesReport
The declared exports.peer_files block as it appears in a ScopeReport.
PinnedProgramReport
One element of ScopeReport::pinned_programs: which copy of a program a tool pins a download of the session runs. path is absent for missing, url and sha256 are present only for pinned, and reason only for missing.
PreopenReport
One artifact’s resolved WASI preopen as it appears in a ScopeReport — and therefore in mur run --explain-scope, in mur doctor, and in trace.jsonl’s session_start.effective_grants.
RouteInputs
What route_table decides presence from, gathered by RouteInputs::new.
RouteReport
One row of ScopeReport::routes: whether this capsule has the route, and what holds it.
RuntimeDirReport
What the session’s runtime directory, or its records directory, is to the capsule’s commands — --explain-scope’s Runtime directory and Records directory blocks, session_start.effective_grants.runtime_dir and .records_dir and mur doctor’s sections, all from [runtime_dir_report] and [records_dir_report].
ScopeReport
Read-only answer to “what would this capsule actually be allowed to do on this host?”.
StateStoreReport
One artifact’s durable state grant as it appears in a ScopeReport.
TempDirReport
The session’s temporary folder, and whether a literal /tmp reaches it — --explain-scope’s Temporary folder block, session_start.effective_grants.temp_dir and mur doctor’s section, all from [temp_dir_report]. Field names are the JSON keys.
UnconfinedReport
What an unconfined session’s subprocesses run as: ScopeReport::unconfined.

Enums§

FilesystemRestriction
What the filesystem mechanism this session installs restricts, as a stable wire name.
PreopenSurface
The filesystem surface one artifact’s guest is preopened into, as a stable wire name.
Route
One route a capsule can run code on, as RouteReport::route names it.
RuntimeDirReach
How one artifact reaches the runtime directory, as PreopenReport::runtime_dir_reach carries it.
ShortfallCause
Why a containment floor is unmet, which decides what an operator is told to change: a host that cannot back the class, or one of the two capsule-side causes no host can fix.

Constants§

HOST_PROCESS_MECHANISM
The mechanism of a RouteReport whose route the session’s class does not cover: the code runs as part of the mur process, or as a child it starts outside the class.
UNCONFINED_APPLIES_TO
The subprocess routes an unconfined session runs as the operator, as UnconfinedReport::applies_to names them.

Functions§

applied_mechanism
The wire name of the tier a shell command of a capsule declaring declared runs under on the host probe read: ContainmentDecision::enforcement_tier, which is what ShellEnforcement::resolve installs for every subprocess. Spelled as ScopeReport::enforcement_tier spells a tier.
attach_extra_roots
Every report that reaches the runtime directory given roots, the session’s extra roots (crate::guest_roots::extra_guest_roots). stage_session, mur run --explain-scope and mur doctor all call it, so the three agree.
check_containment_floor
The refusal gate: Ok(()) when the session’s achieved class (ContainmentDecision::achieved) meets or exceeds the declared floor, RuntimeError::ContainmentFloorUnmet otherwise.
containment_shortfall_reason
Why achieved falls short of declared, naming the missing mechanism rather than the missing class. None when the floor is met.
detect_containment_decision
Probes this host once and decides for a capsule declaring declared, with neither capsule-side cap, returning the probe’s sealed shortfall beside it.
detect_sealed_shortfall
Why this host cannot back sealed, or None when nothing keeps it below, from a reading taken here.
detect_userns_grant
Where this host’s unprivileged-user-namespace permission comes from, or None off Linux, where the question has no answer rather than a negative one.
doctor_runtime_dir
mur doctor’s Runtime directory, Records directory and Temporary folder sections for a capsule declaring declared, run from workdir: the same [runtime_dir_report], [records_dir_report] and [temp_dir_report] on the tier probe’s ContainmentDecision applies, its ruleset ABI and mount namespace, or why HOME cannot hold them.
explain_scope
Builds a ScopeReport for policy against this host, with declared as the already- combined floor. Takes one crate::sandbox::HostProbe, so the tier, the shortfall and the grant it reports all describe one host at one moment.
install_from_places
ScopeReport::install_from for policy: empty without an install grant.
read_only_advisory_for
The allowlisted binaries a declared capabilities.filesystem.read_only is only advisory against: those whose own file I/O the dispatch-time write-intent analyser cannot read, in shell_allow order.
render_images
The Images block of mur run --explain-scope. Starts with a blank line and ends with a newline.
render_install
The install skill, install tool and install from lines of the scope report: which skills and tools a pull may install, <none> for a list the capsule left empty, and the places it may install them from (install from: stores or install from: stores, sources), printed only for a capsule holding an install grant.
render_parent_workdir
The Parent work folder block of mur run --explain-scope, for a delegated child whose work folder started as a copy of its parent’s. Starts with a blank line and ends with a newline.
render_read_only
The read_only block of the scope report: the declared paths, then one line saying whether the protection is enforced for every readable call or advisory against a named binary.
render_records_dir
The Records directory block of --explain-scope and mur doctor, on render_runtime_dir’s terms. Ends with a newline.
render_routes
The Routes block --explain-scope and mur doctor print: one line per route, saying whether the capsule has it and what holds it, with an uncovered present route’s note under it. Starts with Routes and ends with a newline.
render_runtime_dir
The Runtime directory block of --explain-scope and mur doctor: its path, and whether the capsule’s commands can change it. Ends with a newline.
render_temp_dir
The Temporary folder block of --explain-scope and mur doctor: its path, the value of TMPDIR, and whether a literal /tmp reaches it. Ends with a newline.
route_table
The route table: one RouteReport per Route::ALL entry, in that order, for a capsule with inputs whose session installs the tier named enforcement_tier.
uncovered_route_warning
The W-SEC-034 message for a capsule declaring declared with routes, or None when it does not fire: below a scoped floor, or when no present route lies outside the class.
warn_on_uncovered_routes
Prints W-SEC-034 when uncovered_route_warning fires: to stderr, and to the session’s bootstrap log when bootstrap_log names a records directory. The one emitter the launch and mur doctor (with None) both call.