Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

ronly — read-only sandbox for untrustworthy agents
Drop into a shell session where everything looks normal but
destructive operations are blocked at the kernel level.
Linux only. Runs rootless via user namespaces on any
kernel 4.6+ (Debian 11+, RHEL 8+, Ubuntu 16.04+). Falls
back to privileged mode if user namespaces are unavailable.
 $ kubectl exec -it debug-pod -- ronly
 ronly: using user namespaces (--rootless)
 root@debug-pod:~# top -bn1 | head -5
 top - 14:23:01 up 42 days, load average: 2.31, 1.87
 Tasks: 312 total, 1 running, 311 sleeping
 %Cpu(s): 8.3 us, 2.1 sy, 0.0 ni, 89.1 id
 MiB Mem: 32168.0 total, 12042.3 free
 root@debug-pod:~# cat /var/log/syslog | grep error
 Mar 24 09:14:02 prod payment-svc: connection error
 root@debug-pod:~# rm /etc/hosts
 rm: cannot remove '/etc/hosts': Read-only file system
 root@debug-pod:~# kill 1
 bash: kill: (1) - Operation not permitted
 root@debug-pod:~# docker run nginx
 ronly: docker run is blocked (read-only session)
HOW IT WORKS
 1. Read-only filesystem — mount namespace with root
 bind-mounted read-only. Writes fail with EROFS.
 Writable tmpfs at /tmp for scratch space.
 2. seccomp-bpf — blocks kill, unlink, rename, truncate,
 mount, reboot. ptrace write ops blocked but read ops
 allowed (so strace works). ps, top, and /proc show
 real host processes — kill is blocked by seccomp.
 3. Tool shims — ronly copies itself into /tmp under
 names like "docker" and "kubectl" (one copy, rest are
 hard links) and prepends that dir to PATH. The shell
 finds the shim, ronly checks argv[0], and either execs
 the real binary (read-only subcommands) or exits with
 an error (write subcommands).
Network is not restricted. The agent can make outbound
connections. Layer your own network policy if exfiltration
is a concern.
USAGE
 ronly [OPTIONS] [COMMAND...]
With no arguments, execs $SHELL (or /bin/bash).
 --rootless force rootless mode (user namespaces)
 --privileged force privileged mode (requires root)
 --tmpfs-size SIZE writable /tmp size (default: 64M)
 --extra-shims DIR additional shim directory
 --no-shims disable all shims
 --no-network disable all network access (CLONE_NEWNET)
 --writable PATH empty writable tmpfs at PATH
 --help show this help
 --version show version
Two modes exist because not all environments support both.
Rootless works on most modern kernels without root, but
some hardened systems and container runtimes disable user
namespaces. Privileged mode covers those cases. By default
ronly tries rootless first and falls back to privileged.
It prints which mode it's using to stderr.
BUILT-IN SHIMS
Some tools talk to sockets/APIs rather than the filesystem,
so a read-only mount alone doesn't stop them.
 docker — ps, logs, inspect, stats, top, images, info,
 version, events, diff, network ls/inspect,
 volume ls/inspect
 kubectl — get, describe, logs, top, explain, version,
 cluster-info, api-resources, api-versions,
 config view/current-context/get-contexts,
 auth can-i/whoami
Everything not listed is blocked. Add custom shims with
--extra-shims DIR.

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /