The container intentionally restricts certain operations:
| Resource | Access | Purpose |
|---|---|---|
| Network | proxy-filtered (Vertex AI, PyPI, GitHub, agent-specific) | Prevents data exfiltration |
| Proxy source IP | when the proxy has a fixed network IP (as on Podman), only the paired agent container's IP is accepted | Defense-in-depth: prevents other containers/hosts from riding the proxy's egress allowlist |
| Host working directory | not mounted | Code lives in a separate named volume, synced via git (see Code Synchronization) — the agent never touches host files directly |
| gcloud credentials | never enter the agent's container; a non-functional stub ADC file is injected instead | Real credentials live only on the network-filtering proxy sidecar, which signs Vertex AI requests on the container's behalf |
| Agent config and session state | copied in, then stored on the private session volume | Prevents host config poisoning while preserving settings and history across container upgrades |
~/.gitconfig |
host config is read-only; a writable copy is persisted at /pvc/.gitconfig for local and --host remote sessions. The author identity is additionally resolved on the host via git config (honoring global, XDG, system, and includeIf sources) and applied inside the container when the seeded config lacks one |
Git identity |
| SSH keys | not mounted | Prevents git push via SSH |
| GitHub CLI config | not mounted | Prevents cached host credentials |
GH_TOKEN (host) |
never propagated | Set PAUDE_GITHUB_TOKEN before create/start; the real token goes only to the proxy sidecar, never the agent's container |
| Git credentials | not mounted | Prevents HTTPS git push |
These exfiltration paths have been tested and confirmed blocked:
| Attack Vector | Status | How |
|---|---|---|
| HTTP/HTTPS exfiltration | Blocked | Internal network has no external DNS; proxy allowlists only approved domains |
| Git push via SSH | Blocked | No ~/.ssh mounted; DNS resolution fails anyway |
| Git push via HTTPS | Blocked | No credential helpers; no stored git credentials (github.com itself is reachable by default, but there's nothing to authenticate a push with) |
| GitHub CLI write ops | Relies on token scope — use a read-only fine-grained PAT | Use a read-only PAT via PAUDE_GITHUB_TOKEN; host GH_TOKEN never propagated |
| Modify cloud credentials | Blocked | Real credentials never reach the agent's container (see gcloud credentials, above); stored only on the proxy sidecar — see Remote Hosts & Docker Backend for how this differs between Podman and Docker |
| Escape container | Blocked | Non-root user; standard Podman isolation |
The long-running agent container itself always runs as the non-root paude user (see "Escape container" above) — the agent's shell and every session command execute as paude, never root. A small number of short-lived, narrowly-scoped helper operations do run as root; they're listed here for transparency, and tracked as RUNTIME-006 for further reduction.
| Operation | Why root is needed | Scope limits |
|---|---|---|
Backup archive helper (volume_archive.py) |
/pvc accumulates files from multiple owners over a session's life — root-owned 0600 agent state, nested-container files carrying another container's SELinux MCS category, pre-UID-pin drift artifacts. A non-root, SELinux-confined read fails partway through a multi-GB backup with "Permission denied"; paude backup is designed to fail loudly rather than silently produce an incomplete archive |
Read-only (:ro) volume mount; throwaway container destroyed after use; no capabilities added beyond --user root and disabling SELinux confinement |
Volume ownership reconciliation (reconcile_volume_ownership) |
Migrates volumes created before the runtime UID was pinned to 1000:0 (2026-08-10) onto the current pinned identity |
Runs inside a container the invoking user already controls; target UID/GID is resolved at runtime via id -u/-g paude, never hardcoded; the actual chown -R only fires when ownership has actually drifted |
Config/credential file writes (inject_file, replace_file, ConfigSyncer) |
podman exec only runs as the container's default user unless overridden; writing a file the agent doesn't yet own (proxy CA cert, /credentials/ staging) needs root for one atomic write |
Root scope lasts for a single exec call; file ownership is corrected (chowned back to paude) immediately after |
# SAFE: Network filtered, cannot exfiltrate data
paude create --yolo
# DANGEROUS: Full network access, can send files anywhere
paude create --yolo --allowed-domains allThe --yolo flag enables autonomous execution (no confirmation prompts). This is safe when network filtering is active because the agent cannot exfiltrate files or secrets even if it reads them.
Do not combine --yolo with --allowed-domains all unless you fully trust the task.
--allowed-endpoints HOST:PORT is narrower than a global port exception: the
proxy requires both an allowed-domain host match and the exact endpoint match.
Endpoint rules never authorize a host on their own or grant that port elsewhere.
The agent operates on its own copy of your code, not your host files. Your protection is git itself. Push important work to a remote before running in autonomous mode:
git push origin mainIf something goes wrong inside the container, recovery is a clone away, and your host files were never at risk in the first place.
These risks are accepted by design:
- Workspace destruction: The agent can delete files (including
.git) in the container's own copy of the code. Mitigation: push to remote before autonomous sessions, so a destroyed container's copy is always recoverable. - Secrets readable: Any
.envfile synced into the container — via--gitorpaude cp— is readable there. Mitigation: network filtering prevents exfiltration; avoid--allowed-domains allwith sensitive workspaces, and don't sync in.gitignored secrets. - No audit logging: Commands executed aren't logged. This is a forensics gap, not a security breach vector.
- Port-forward exposure:
--forward-port HOST_IP:HOST:CONTAINERwith a non-loopbackHOST_IP(e.g.0.0.0.0) exposes the forwarded container port to your LAN with no additional authentication — anyone who can reach that host/port gets the same access a local loopback connection would. Mitigation: only bind non-loopback addresses on trusted networks; the default forms (barePORT/HOST:CONTAINER) bind loopback only.