A long sudo credential cache is unlimited root for every process you run
scope: generic · severity: trap · confidence: proven · subsystem: setup
pmbootstrap needs root, and the obvious way to stop it prompting is:
Defaults:you timestamp_timeout=9999That is a 167-hour root credential cache, and it is not scoped to pmbootstrap. It is scoped to you. For a week, anything running under your account gets silent root with no prompt, no allowlist and no audit trail: an agent, a build script, a compromised dependency, a prompt injection that arrived in a log file something read.
The failure mode is not “the agent turns evil”. It is that the blast radius of any mistake, from any source, becomes the whole machine — and you cannot afterwards tell what used it.
The intercept. pmbootstrap escalates through exactly one hook:
def sudo(cmd): sudo = which_sudo() # honours $PMB_SUDO return [sudo, *cmd] if sudo else cmdSo PMB_SUDO=<broker> routes every root request through a program you control,
as argv, which you can validate. It is a supported upstream feature.
The surface is smaller than it looks. A real pmbootstrap chroot -- true
plus shutdown makes 72 root requests across 11 verbs (mount, umount, sh,
mknod, chmod, ln, rm, mkdir, touch, env, losetup), and every path argument is
inside the pmbootstrap work directory. Measure it on your own setup rather
than trusting that list.
The remedy is to need no root at all. porthole sandbox up runs the work
in a persistent rootless container where you are uid 0 inside and your own
unprivileged uid outside, so pmbootstrap uses no sudo whatsoever and no sudoers
entry is granted. An escape reaches your uid, not the machine.
A validating broker was tried and then deleted, 2026-08-29. PMB_SUDO
pointed at a program that confined paths to declared roots, refused
non-pmbootstrap verbs and audited every decision — far better than a blanket
cache, and still not enough. chroot <dir> <cmd> runs an arbitrary command as
root, and root inside a chroot can escape a chroot; a broker confines the
directory, not the payload. Since pmbootstrap legitimately needs to write
executables into a chroot and run them, any allowlist that lets pmbootstrap
work lets a payload work.
So the remaining lesson is sharper than “broker it”: a fallback that still exists is the one a stuck agent reaches for, and one that buys false confidence is worse than none. Removing it left exactly one answer.
The one thing worth doing even if you do nothing else: delete the
timestamp_timeout line. A five-minute cache instead of a week-long one turns
every escalation after the first into one you were present for.
Generalises past pmbootstrap: the same shape applies to any agentic workflow
that needs a privileged tool — Docker socket access, terraform apply,
kubectl with cluster-admin. Ask what the tool actually needs, discover it
empirically, and give it exactly that – or, better, an environment where it
needs no privilege to give.
Related: no-passwordless-sudo-disables-the-whole-toolbox, running-a-device-script-on-the-host.
