Skip to main content

CapabilityPolicy

Struct CapabilityPolicy 

Source
pub struct CapabilityPolicy {
Show 28 fields pub network_allow: Vec<String>, pub peer_fetch_allow: Vec<String>, pub unix_sockets_allowed: bool, pub filesystem_scope: Option<String>, pub workdir_exec_allowed: bool, pub read_only_paths: Vec<String>, pub shell_allow: Vec<String>, pub spawn_allow: Vec<String>, pub spawn_workdir_snapshot: Vec<String>, pub shell_strip_env: Vec<String>, pub shell_baseline_env: Vec<String>, pub shell_interpreter_runtime: Vec<InterpreterRuntimeGrant>, pub shell_staged_runtime: Vec<StagedRuntimeGrant>, pub shell_derived_interpreter_runtime: Vec<DerivedInterpreterRuntime>, pub shell_trust_store: Vec<TrustStorePath>, pub host_paths: Vec<HostPath>, pub env_allow: Vec<String>, pub limits: ExecutionLimits, pub resources: HostResourceLimits, pub declared_resources: ResourceCapabilities, pub containment_floor: ContainmentClass, pub state_declared: bool, pub conversation_declared: bool, pub plan_submit: bool, pub install_skill: Vec<String>, pub install_tool: Vec<String>, pub install_from_sources: bool, pub declared_deadline_seconds: Option<u64>,
}

Fields§

§network_allow: Vec<String>§peer_fetch_allow: Vec<String>

From capabilities.peer_fetch.allow: the peers this capsule may redeem a peer-file handle against. Empty by default, which is deny — and which is also why no fetch-peer-file tool manifest is written and the capsule’s model never sees the tool exists.

A separate list from Self::network_allow, enforced with the same rule matcher but never merged into it. Ingesting a peer’s bytes lands a file in this capsule’s own workdir, so it is a prompt-injection surface and deserves its own operator control; a destination in network.allow is not redeemable unless it also appears here, and declaring it here does not widen network.allow.

§unix_sockets_allowed: bool

From capabilities.network.unix_sockets. false by default, which makes the shell subprocess tree’s socket(AF_UNIX, ...) calls fail with EACCES at the kernel level on both Linux tiers — network_allow above governs IP destinations only and would otherwise leave a local daemon socket (/var/run/docker.sock — host root) completely unmediated. true simply omits that seccomp rule; it is capsule-wide, not per-socket-path. See sandbox::denied_socket_domains.

§filesystem_scope: Option<String>§workdir_exec_allowed: bool

From capabilities.filesystem.workdir_exec. false by default, which withholds the Landlock Execute right from the workdir’s own PathBeneath rule — see sandbox::linux_enforce::workdir_access_rights. With it withheld the kernel refuses to exec anything under the workdir on the resolved path itself, so shell_allow is enforced completely: a binary copied or compiled into the workdir cannot run under any name.

true gives the right back for compile-and-run workflows and accepts, explicitly, that shell_allow is then unenforceable for anything inside the workdir. That is why this field is the one grant in this struct that also lowers the session’s achieved containment class (see crate::containment::achieved_containment_class) — nothing else here can.

§read_only_paths: Vec<String>

From capabilities.filesystem.read_only: workdir subtrees the capsule may read but must not write, in the same vocabulary Self::filesystem_scope uses. Empty by default, which is the whole workdir writable.

Carried here as the declared strings and lowered once at staging into crate::protected_paths::ProtectedPaths, which is what the dispatch check consults — so a malformed entry refuses the launch rather than one call at a time. Unlike every other field here this one grants nothing: it can only subtract from what the workdir preopen already allows.

§shell_allow: Vec<String>§spawn_allow: Vec<String>§spawn_workdir_snapshot: Vec<String>

From capabilities.spawn.workdir_snapshot: the full names in Self::spawn_allow whose every delegation starts in a copy of this session’s work folder, made by this runtime before the child process starts. Empty by default, which starts every child in an empty folder.

§shell_strip_env: Vec<String>§shell_baseline_env: Vec<String>§shell_interpreter_runtime: Vec<InterpreterRuntimeGrant>

Typed interpreter-runtime grants from capabilities.shell.interpreter_runtime: each names an already-allowlisted binary and the exact host directories outside the workdir its import machinery needs, with a per-directory list_dir enumerability flag. Empty unless the manifest declares them. Consumed on KernelFull to add narrow Landlock grants (see sandbox::resolve_interpreter_runtime_grants) and to fire W-SEC-009.

§shell_staged_runtime: Vec<StagedRuntimeGrant>

Typed staged-runtime grants from capabilities.shell.staged_runtime: each names an already-allowlisted binary, the absolute host path of a pinned runtime tree, and the pin identifying that tree’s build. Empty unless the manifest declares them.

Consumed at staging to enforce that declaring one requires an effective sealed floor (see crate::staged_runtime::check_staged_runtime_floor) and to render the staged runtime section of --explain-scope. Per-binary mutually exclusive with Self::shell_interpreter_runtime, which the manifest parser already guarantees.

§shell_derived_interpreter_runtime: Vec<DerivedInterpreterRuntime>

The runtime directories of each shell_allow binary the runtime recognises as an interpreter, as that interpreter reported them (see [crate::interpreter_runtime]). Not a manifest field: empty from capability_policy_from_runtime_manifest, filled once by stage_session and by mur run --explain-scope through crate::interpreter_runtime::derive_interpreter_runtimes. Each becomes a readable, non-executable Landlock grant (sandbox::resolve_derived_interpreter_grants) and, on sealed, an optional composed-root bind.

§shell_trust_store: Vec<TrustStorePath>

The host’s TLS trust store, as staging found it for a capsule with a non-empty shell_allow and a non-empty network_allow (see [crate::trust_store]). Not a manifest field: empty from capability_policy_from_runtime_manifest, filled once by stage_session and by mur run --explain-scope through crate::trust_store::derive_trust_store. Each becomes a readable, non-executable Landlock grant (sandbox::resolve_trust_store_grants), listable for a directory.

§host_paths: Vec<HostPath>

The host folders ~/.murmur/config.yaml‘s host_paths: lends every contained capsule on this host, checked on this host, in config order (see crate::host_paths). Not a manifest field: empty from capability_policy_from_runtime_manifest, filled by mur run (and --explain-scope) from the global config alone. On landlock+seccomp each becomes a Landlock rule for commands and plan shell steps; on sealed also a required bind at its own path. Never executable. WASM tools’ preopens do not include them.

§env_allow: Vec<String>

Host env var names a WASM guest may observe, from capabilities.env.allow. Empty by default: a guest sees only the runtime’s own MURMUR_* injection unless the manifest names a variable here. shell_strip_env and the credential patterns still apply on top, so a credential-shaped name declared here is stripped anyway.

§limits: ExecutionLimits

Execution limits applied to every guest store in the session. Always fully resolved — capability_policy_from_runtime_manifest substitutes a default for each field capabilities.limits omits, so there is no “unset” state here and a silent manifest yields ExecutionLimits::default rather than no limits.

§resources: HostResourceLimits

OS-level bounds applied to every subprocess the session spawns — rlimits, the Linux cgroup v2 scope, and the workdir-size ceiling. Resolved on exactly the same terms as limits above (each omitted capabilities.resources field replaced by its default, no “unset” state), but a completely different subject: limits bounds a WASM guest inside its wasmtime store, this bounds the processes the host forks. See crate::resources.

§declared_resources: ResourceCapabilities

The manifest’s own capabilities.resources block, every omitted field still None. Self::resources is what a contained session applies; an unconfined session (a Self::containment_floor of ContainmentClass::Unconfined) applies only what this declares, creates a cgroup scope only when it declares a cgroup_* field and runs the workdir guard only when it declares workdir_max_bytes.

§containment_floor: ContainmentClass

The containment class this capsule asked for, from capabilities.containment.

Unlike every other field here it is a requirement, not a grant — and unlike StageRequest::declared_containment_floor it is only the manifest’s own vote, before the workspace config and --containment are folded in. stage_session overwrites it with the combined floor as soon as that is known, so anything reading it off a StagedSession sees the effective value; the manifest-only value exists so a CapabilityPolicy built straight from a manifest is still self-consistent.

Read by sandbox::ShellEnforcement::resolve to decide whether a sealed-capable host actually installs a composed root for this session — a capsule that declared scoped must keep getting scoped’s mechanism. See sandbox::applied_tier.

§state_declared: bool

Whether the capsule’s own top-level capabilities.state block was declared.

Not a grant, and the only field here that is not: a durable state store is granted per artifact, so a capsule-wide declaration reaches nothing at all. It is recorded so stage_session can say that once (W-SEC-014) instead of leaving an operator to discover an empty directory, and it is read by nothing else.

§conversation_declared: bool

Recorded for the same reason Self::state_declared is, and applied just as little: the murmur:conversation/read grant is per artifact, so a capsule-wide declaration reaches nothing and stage_session says so once (W-SEC-016).

§plan_submit: bool

From capabilities.plan.submit: whether this capsule’s model is offered the runtime-provided submit-plan tool. false by default, which is deny — and which is also why no submit-plan tool manifest is written and the capsule’s model never sees the tool exists.

It grants no reach of its own: every step of a submitted plan runs through this same session’s tool dispatch, its shell allowlist and its spawn grant, so a plan reaches exactly what the model could already call one call at a time.

§install_skill: Vec<String>

From capabilities.install.skill: the entries naming which skill artifacts a pull (manage.pull or the pull-artifact tool) may install into this session, verbatim and in declaration order. Empty by default, which is deny. With Self::install_tool also empty, every pull is refused.

A pulled skill gains no grant of its own; see install_grant.

§install_tool: Vec<String>

From capabilities.install.tool: the entries naming which tool artifacts a pull may install, verbatim and in declaration order. Empty by default, which is deny.

A pulled tool joins the session’s dispatch allowlist and dispatches on this policy’s own ceiling; it gains no grant of its own.

§install_from_sources: bool

From capabilities.install.from: true for [stores, sources], under which a pull the stores cannot answer is fetched from the scope’s GitHub source. false by default.

§declared_deadline_seconds: Option<u64>

capabilities.limits.deadline_seconds exactly as the manifest declared it — None when it declared nothing. Retained undefaulted alongside the fully-resolved limits above purely so hook calls can apply their own, lower default without mistaking an explicit 600 for silence. See Self::hook_limits.

Implementations§

Source§

impl CapabilityPolicy

Source

pub fn hook_limits(&self) -> ExecutionLimits

Execution limits for hook lifecycle calls — Self::limits with the hook-specific deadline default substituted when the manifest declared none.

A hook call is one bounded piece of work, so it does not inherit the capsule-wide ten-minute budget that exists for a capsule’s whole run: a wedged hook would otherwise stall the session for most of that, every event. An explicitly declared deadline_seconds still wins, for hooks as for every other guest.

Trait Implementations§

Source§

impl Clone for CapabilityPolicy

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CapabilityPolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for CapabilityPolicy

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for CapabilityPolicy

Source§

impl PartialEq for CapabilityPolicy

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for CapabilityPolicy

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

The type of the none-equivalent value that NoneValue::null_value produces.
Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more