Filesystem grants

What an agent may read and write is declared in its profile and installed into a kernel sandbox at startup. Those are not the same thing, and the gap between them is where the confusing failures live โ€” a grant can be written down, dropped by policy, and never reach the kernel at all.

mur agent perm list-paths mur
agent 'mur' โ€” sandbox enforcing (macos-sbpl)

READ
  โœ“ /Volumes/Firecuda4tb/Projects/mur
  โœ— /Volumes/Firecuda4tb/Projects/cc-proxy
      dropped โ€” path does not exist on disk
  โœ“ /Users/david/.mur/skills

Three states, not two

StateWhere it livesWhat it means
grantedprofile.yamlYou asked for it
admittedafter policyIt survived the checks โ€” a path that does not exist on disk is dropped
enforcedthe running sandboxThe kernel actually received it

list-paths shows all three at once: โœ“ for a grant that reached the kernel, โœ— dropped with the reason, and a plain ยท for a grant recorded but not yet enforced because the agent is not running.

The header is the fourth fact โ€” whether the sandbox is enforcing at all, and which backend installed it. An agent whose seal failed is not an agent with no grants; it is a different situation entirely, and the two used to look identical.

Granting

mur agent perm allow-read  mur /path/to/tree
mur agent perm allow-write mur /path/to/tree
mur agent perm deny-path   mur /path/to/secret
mur agent perm list-hosts  mur

Grants are recursive: allowing a directory allows everything under it. Changes take effect on the agent's next start โ€” the sandbox is installed once, at startup, and cannot be widened afterwards.

allow-write refuses a path that does not exist, so a write grant is always for something real. When a write is denied at run time, the agent's own error names the nearest existing ancestor you could grant instead of the path it tried.

Why a grant gets dropped

The sandbox backends differ in what they can express. Linux Landlock has no deny rule, so an allow that overlaps a protected path has to be dropped whole; macOS SBPL can install the allow and re-close the protected paths after it. A grant that works on one host can therefore be dropped on the other โ€” which is why the drop is reported per path, with its reason, rather than summarised.

The kernel is not the only gate. MUR's tools check the same grants in-process before acting, and on Linux that check is the only place a deny-within-allow is enforced, precisely because Landlock cannot express one. A path can therefore be refused by the tool while the kernel would have allowed it โ€” see Troubleshooting for what that looks like.

Two files are always denied to the agent itself, on every backend: its own profile.yaml and its identity.key. An agent cannot read its own configuration or its private key, so anything the agent needs to know about its own grants has to be handed to it, not read back.

That is self-protection, and it is the narrow case. A larger set of paths is refused to every agent โ€” other agents' directories and signing keys, ~/.mur/secrets, ~/.mur/auth.json, the host identity.key, the runtime binary and the autostart directories. Those are listed with their reasons under Troubleshooting.

  • Build Lane โ€” allow-spawn-dir, for toolchains that compile and then run their own output.