fix(podman): keep host repo ownership on rootless podman via keep-id#69
Merged
Conversation
Rootless podman maps the host user to container-root, so the entrypoint's chown of the bind-mounted repo to the uid-1000 sluice user landed host-side as a subuid - after one run the host user could no longer write their own repo (and sluice's own host-side config writes EACCES'd). resolve_podman_userns adds --userns=keep-id:uid=1000,gid=1000 on rootless podman >= 4.3, mapping the host user straight onto the sluice uid: the mount is writable without a chown (which then no-ops on it) and the repo stays host-owned, while container- internal overlay/state volumes are still chowned as before. Docker and rootful podman are untouched (early-return no-op). Older podman warns with the 'podman unshare chown' recovery. Version gate + no-ops covered by verify-podman-userns-unit.bats (rootless podman itself runs only on the best-effort CI leg); docs/hardening.md documents the behavior.
Pyronewbic
added a commit
that referenced
this pull request
Jul 6, 2026
…localhost/, rootless caveats) (#71) Post-review cleanup of the pre-existing findings review-launcher surfaced on #67 (the HIGH chown one shipped as #69); none are regressions. - build(): hoist `_chash="$(config_hash)"` out of the `local args=(...)` array. local returns 0, so a failing hash (shasum rc 127) baked an empty confighash label under set -e, after which every maybe_build silently rebuilt. Assigned alone the failure propagates and the build dies. - ls/prune: strip podman's `localhost/` image-name prefix at the two `image ls` seeds so the name matches the canonical sluice-<slug> everywhere downstream (ps status filter, box_blocked_count, the ${#sluice-} receipt slug, remove_box_volumes label) - it was breaking all of them on podman. No-op on docker (never emits the prefix). - doctor: a shared _rootless_podman helper surfaces the rootless-podman host limits - pids/memory caps need cgroups-v2 + systemd delegation, ports <1024 can't bind (flagged per configured port), netfilter modules must be loaded; additive rootless_podman JSON field; docs/hardening.md documents all three. Tests: verify-build-hash-unit.bats (new), + podman-prefix and rootless-doctor cases in verify-ls-egress-unit / verify-doctor-checks. Unit 318 green, acceptance 16 green; podman-specific paths ride the best-effort podman CI leg.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug (pre-existing, HIGH — surfaced by review-launcher on #67)
On rootless podman the host user maps to container-root, so the entrypoint's chown of the bind-mounted repo to the uid-1000
sluiceuser (core/entrypoint.sh) lands host-side as a subuid. After one run the host user can no longer write their own repo — and sluice's own host-side config writes (apply_allowlist) EACCES and die. On docker the mount keeps the host uid so the chown no-ops; the bug is podman-only. The repo's own test harness documents the subuid behavior, but the launcher never handled it for real project dirs.The fix
resolve_podman_userns(new,src/40-runtime.sh) adds--userns=keep-id:uid=1000,gid=1000on rootless podman ≥ 4.3, mapping the host user straight onto the sandbox uid. Then:Injected via
RUNTIME_RUN_OPTS(the same channel kata uses), called fromstart()beforeruntime_run. Docker and rootful podman are a strict no-op (early return). Older podman (< 4.3, nokeep-id:uid=) warns and falls back to today's behavior with the recovery command:podman unshare chown -R 0:0 "$PWD".Why keep-id and not "skip the chown"
The chown is load-bearing: without it (or keep-id) the uid-1000 sandbox user can't write the podman bind mount at all. keep-id removes the need for it on the project dir while preserving host ownership — the only approach that fixes the re-own without breaking writability.
Tests / verification
verify-podman-userns-unit.bats(7 tests, no Docker): the version gate (4.9.3/5.0.0 inject; 4.2.0 warns + falls back), rootful/docker no-ops, kata-compose append, and a structural guard thatstart()calls it beforeruntime_run. This is the only local coverage — rootless podman runs only on the best-effort CI leg, which exercises the integration path.make test-acceptancegreen (16/16),build-check+lintclean, full unit lane 310 green.docs/hardening.mddocuments the behavior + the older-podman recovery.Scoped to this one pre-existing finding; the other 5 from the #67 review remain separate follow-ups.