roadmap - pprados/pysandboxes GitHub Wiki
This version is a first implementation offered to the community. It allows for testing and demonstrating the validity of the approach.
It ensures that the patches for Python functions are correct and do not cause bugs in applications. If you find a case that presents a problem, open a ticket with a scenario to reproduce it. We will provide a fix as soon as possible.
It also verifies the relevance of the multiple sandbox encapsulation strategy. Depending on the configured rules and selected provider, the layers can filter network access and deny access to files matching patterns. Provider limits apply: Landlock denies native TCP bind/connect by default on ABI v4+ but cannot filter UDP; QEMU applies expose-ro with a read-only 9p export. Since OS providers do not rename directories during an expose mapping, the py-sandbox layer handles this.
We have a planned roadmap. Developments will arrive gradually, with no specific order:
- Guards
- Management of Denial of Service
- Management of regular expressions
- OS Compatible
- Windows
- Mac OS (see https://cursor.com/fr/blog/agent-sandboxing)
- OS-sandboxes
- Basic
- sub interpreter
- Landlock: refuse
connect()to a named Unix socket not covered by anexpose-rwrule, the rule every other provider applies. Landlock cannot filter it, so a seccomp user-notification filter sends each Unixconnect()to the parent, which checks the path, connects itself and hands the descriptor back (SECCOMP_IOCTL_NOTIF_ADDFD), leaving no window to change the path after the check. - Sandbox utilities
- Proxy (SOCKS/HTTP over a Unix socket bound into the sandbox, relayed by socat: filtering by domain, not only by IP)
- Container
- Flatpak
- rpm-ostree unprivileged
- bwrap-oci
- gVisor (user space kernel simulation, without docker)
- Firecracker
- VM
- multipass
- lxc
- vagrant
- micro-VM
- QEMU-microvm
- Firecracker
- Fargate
- Kata Containers (compatible classical containers management)
- Smolvm
- Others strategies
- Apple
- App Sandbox
- sandbox-exec
- Basic
- Features
- Compile a part of code
- Propagate the tracability id
- Use anyio
- Use Condon JIT
- DevContainer
Other OS-level sandbox solutions will be integrated. Docker and Podman are covered through the unshare provider.
If your application itself runs in a container, it may not be able to launch another inside (depending on the parameters). This is also the case for solutions relying on Linux capabilities.
| Solution | Privileges Required | Docker Socket Mount | Security | Isolation |
|---|---|---|---|---|
| Docker-in-Docker | Yes (--privileged) |
Optional | Low | High/Medium |
| Podman | No | No | High | High |
| Kubernetes (DinD) | Yes (privileged) | Optional | Low | Medium |
| qemu | No | No | High | High |
Different solutions will be proposed (pre-launch of the sandbox in another container, in parallel; use of emulation solutions, like qemu, that do not require privileges, etc.).
Generated code may never terminate and cause a denial of service. It's not easy to manage this. Indeed, it is easy to identify that a @sandbox function is taking too long to respond, but it is very difficult to interrupt it. It is not possible to kill a thread, unlike a process. A simple malicious regular expression can be exploited to kill the FastAPI server (see Catastrophic Backtracking).
We are considering a solution to identify these situations and kill the offending function if necessary.
Certain regular expression patterns cause problems because they can cause the Python program to become unresponsive. We plan to add a specific filter to refuse the execution of expressions identified as at risk.
To strengthen security, we are considering compiling a part of the project to make it more difficult to access the standard implementations of Python functions.
The protocol break prevents tracking with OpenTelemetry. We want to propagate the necessary information to get a complete trace.
DANGEROUS_PATTERNS = [
# Dynamic code execution
r"\b__import__\b",
r"\bimportlib\b",
r"\beval\s*\(",
r"\bexec\s*\(",
r"\bcompile\s*\(",
r"\btype\s*\(",
r"\bcallable\s*\(",
# Builtins/attribute access
r"\b__builtins__\b",
r"\b__dict__\b",
r"\b__class__\b",
r"\b__globals__\b",
r"\b__setattr__\b",
r"\b__getattribute__\b",
# Introspection
r"\bglobals\s*\(",
r"\blocals\s*\(",
r"\bvars\s*\(",
r"\bdir\s*\(",
r"\bgetattr\s*\(",
r"\bsetattr\s*\(",
r"\bdelattr\s*\(",
r"\bhasattr\s*\(",
# Deserialization
r"\bpickle\b",
r"\bmarshal\b",
r"\bloads\s*\(",
# File access
r"\bopen\s*\(",
r"\binput\s*\(",
r"\braw_input\s*\(",
# Shell patterns
r"\bbash\b",
r"\bsh\b",
r"\bcmd\b",
r"/bin/",
r"\bsubprocess\b",
r"\bos\.system\b",
r"\bpopen\s*\(",
]