Reported from a live deployment of 0.5.0 (the policy from #36, substituted, sha256:d50c6508…), on a snap-installed docker 29.6.1.
The gap
As shipped, the bind allow-list accepts only paths inside P-15 (the project directory), plus named volumes. Measured against the 45 containers running on that host, that rule covers 18 of 45 bind sources: the rest live under /media/... — downloads, audiobooks, documents — and a few sit elsewhere in the operator's home. Those stacks could not be created at all under the shipped policy: docker create was denied on the bind, with no way to express "this root is mine" short of editing the policy by hand.
This is not a defect in the fix — the version-prefix rule is what #35 was about, and it works — it is a missing knob. The list was widened on that host by an accepted-root rule (/media/**, the three named roots, each with traversal still refused) and applied without a daemon restart, which is why the deployment went from 42 to 45 containers.
What to consider
- A parameterised extra-roots placeholder in
skeleton/agent.rego (alongside the existing substitution tokens), so an operator can express "these roots on this host are mine" without hand-editing Rego — with traversal refusal preserved, since a prefix rule is exactly where path.. reaches.
- Or, if the schematic would rather stay strict, a prominent limitation in
SCHEMATIC.md and modules/opa-policy.md saying plainly that anything binding outside P-15 cannot run, so it is discovered while reading rather than while creating a container.
The distinction worth documenting either way: a bind source is the one input to the decision where the operator's real layout, not the API's shape, decides what is legitimate — which is also why /home/cameri/.ssh had to stay out of that host's list while known_hosts was named exactly.
Reported from a live deployment of 0.5.0 (the policy from #36, substituted,
sha256:d50c6508…), on a snap-installed docker 29.6.1.The gap
As shipped, the bind allow-list accepts only paths inside
P-15(the project directory), plus named volumes. Measured against the 45 containers running on that host, that rule covers 18 of 45 bind sources: the rest live under/media/...— downloads, audiobooks, documents — and a few sit elsewhere in the operator's home. Those stacks could not be created at all under the shipped policy:docker createwas denied on the bind, with no way to express "this root is mine" short of editing the policy by hand.This is not a defect in the fix — the version-prefix rule is what #35 was about, and it works — it is a missing knob. The list was widened on that host by an accepted-root rule (
/media/**, the three named roots, each with traversal still refused) and applied without a daemon restart, which is why the deployment went from 42 to 45 containers.What to consider
skeleton/agent.rego(alongside the existing substitution tokens), so an operator can express "these roots on this host are mine" without hand-editing Rego — with traversal refusal preserved, since a prefix rule is exactly wherepath..reaches.SCHEMATIC.mdandmodules/opa-policy.mdsaying plainly that anything binding outsideP-15cannot run, so it is discovered while reading rather than while creating a container.The distinction worth documenting either way: a bind source is the one input to the decision where the operator's real layout, not the API's shape, decides what is legitimate — which is also why
/home/cameri/.sshhad to stay out of that host's list whileknown_hostswas named exactly.