Security Policy¶
Tako VM exists to run untrusted, often AI-generated, Python. Execution safety is the product, so we treat vulnerabilities in the isolation boundary as our highest-priority class of bug. This document explains what we consider in and out of scope, how to report an issue, and how to deploy Tako VM so its security controls are actually in effect.
Reporting a Vulnerability¶
Report vulnerabilities privately through GitHub's coordinated disclosure flow:
- Go to the Security tab of this repository.
- Click Report a vulnerability to open a private advisory.
Please do not open public issues, pull requests, or discussion threads for suspected vulnerabilities until a fix has been released and we have agreed on a disclosure date.
A useful report includes:
- The version, commit SHA, or PyPI release you tested.
- Your configuration relevant to the finding — in particular
container_runtime,security_mode,enable_seccomp, and any job types withnetwork_enabled: true. - A minimal reproduction: the submitted code or request, and the observed versus expected behavior.
- The impact you believe it has (container escape, host access, data exfiltration, denial of service, information disclosure).
Reports that demonstrate a sandbox escape — host filesystem access, code execution outside the executor container, reaching the Docker daemon, or bypassing network isolation — are the most valuable and will be prioritized accordingly.
What to expect¶
- Acknowledgement of your report within 3 business days.
- An initial assessment, including a severity judgment and whether we can reproduce it, within 10 business days.
- Progress updates as we work toward a fix.
- Credit in the release notes and advisory if you want it; tell us how you would like to be named, or if you prefer to remain anonymous.
We support coordinated disclosure and will agree on a public disclosure date with you. We ask for a 90-day disclosure window as a default, shortened if a fix ships sooner or extended by mutual agreement for complex issues.
Safe harbor¶
We will not pursue or support legal action against researchers who, in good faith, find and report vulnerabilities in accordance with this policy, provided they avoid privacy violations, data destruction, and service degradation against systems they do not own. Test against your own deployment, not against other people's hosted instances.
Supported Versions¶
Tako VM is pre-1.0 and under active development. Security fixes are applied to the latest released version on the PyPI tako-vm package and the main branch. We do not backport fixes to older tags. If you are pinning a version, track the latest release and review the changelog before upgrading, since security-relevant defaults may change between releases.
| Version | Supported |
|---|---|
Latest release / main |
Yes |
| Older tagged releases | No |
Security Model¶
Tako VM uses layered isolation. No single layer is treated as sufficient on its own; each is intended to contain failures in the layers above it.
Process isolation (gVisor). When container_runtime: runsc is set, the executor runs under gVisor, a userspace kernel that intercepts and services guest syscalls instead of passing them to the host kernel. This is the primary boundary against kernel-level container escapes and is the recommended runtime for any untrusted workload.
Container isolation (Docker). Each job runs in its own ephemeral container (--rm) with a read-only root filesystem, all Linux capabilities dropped except those required for the privilege drop, and a non-root user (uid 1000) enforced at runtime. Writable space is limited to /output/ and a noexec /tmp/. Containers carry no persistent state between executions.
Syscall filtering (seccomp). A default-deny seccomp profile (SCMP_ACT_ERRNO) allows only a whitelist of syscalls and blocks dangerous ones including ptrace, mount, reboot, sethostname, and init_module. Controlled by enable_seccomp.
Network isolation. Containers run with --network=none by default, which blocks data exfiltration, command-and-control traffic, and access to internal services. Network access is opt-in per job type via network_enabled: true, and when enabled it permits access to any external host — egress filtering is your responsibility (host firewall or Kubernetes NetworkPolicy). Runtime dependency installation and the shared dependency cache are disabled by default to prevent untrusted jobs from fetching and executing package setup code.
Resource limits. Memory, CPU, PID, file-descriptor, file-size, and /tmp size limits, plus enforced execution timeouts, bound the damage from runaway or deliberately abusive code (fork bombs, memory exhaustion, disk filling).
Input validation. Submitted code and inputs are size-capped (100KB code, 1MB input, 300s max timeout by default). Container build inputs — base image, Python version, pip requirements, environment variables, and shared code paths — are validated to reject shell metacharacters, newlines, URL and path specifiers, and directory traversal. Output artifact filenames are checked to block path separators, parent-directory references, and hidden files.
Output handling. stdout, stderr, and artifacts are size-capped, and stack traces are rewritten to strip internal host paths before they are returned.
API front door. The server enforces a maximum request body size and per-client-IP rate limiting by default. Run it behind TLS in production.
A fuller description lives in docs/deployment/security.md.
Threat Model¶
In scope¶
The following are vulnerabilities we want reported and will treat as security issues:
| Threat | Expected mitigation |
|---|---|
| Code execution escaping the executor container to the host | gVisor, container isolation, seccomp |
Bypassing network isolation on a --network=none job |
Docker network namespace |
| Reaching the Docker daemon or socket from executed code | Socket is not mounted into the executor; proxied access only |
| Injection through build inputs (image, version, pip, env, paths) | Input validation |
| Path traversal via artifact filenames or shared code paths | Filename and path validation |
| Resource-limit bypass leading to host denial of service | Memory, CPU, PID, time, and file-size limits |
| Data exfiltration from a no-network job | Network isolation |
| Leakage of host paths or internal state through output or errors | Output and stack-trace sanitization |
| Authentication or rate-limit bypass on the API | API payload and rate-limit controls |
Out of scope¶
These are known limitations of the architecture rather than bugs. They will not generally be treated as vulnerabilities, though we welcome discussion of hardening:
| Item | Reason |
|---|---|
Host kernel exploits when running under runc instead of gVisor |
Standard containers share the host kernel by design. Use gVisor for untrusted code. |
| Compromise of the Docker daemon by an operator with Docker access | Requires privileges Tako VM assumes are trusted. |
| CPU cache, timing, and other side-channel attacks | Shared hardware; requires dedicated hosts or VM-level isolation to address. |
| Observability of execution timing | Job timing is intentionally returned to callers. |
| Vulnerabilities in user-supplied job-type images or dependencies | The operator owns the contents of their images. |
| Misconfiguration that disables a control (see below) | Security depends on deploying with the documented settings. |
For stronger isolation than gVisor provides, run Tako VM on dedicated hosts or pair it with VM-level isolation such as Kata Containers or Firecracker.
Secure Deployment¶
Several defaults in the shipped example configuration favor ease of first-run over maximum hardening. If you are exposing Tako VM to untrusted code in production, do not run with the example defaults unchanged. At minimum:
- Set
security_mode: strict. The default ispermissive, which silently falls back to standardruncif gVisor is unavailable — meaning untrusted code can end up running without the userspace-kernel boundary you expect.strictfails closed instead. - Install and verify gVisor (
docker run --runtime=runsc --rm hello-world) and keepcontainer_runtime: runsc. - Keep
enable_seccomp: true. - Terminate TLS in front of the API and keep rate limiting enabled.
- Keep
network_enabledoff for every job type that does not strictly require egress, and apply external egress filtering to those that do. - Keep runtime dependency installation and the shared dependency cache disabled unless you fully trust the jobs and the install path.
- Keep the host kernel, Docker, and gVisor patched.
- Review execution records and logs, and re-test your isolation controls after upgrades, since security-relevant defaults can change.
A deployment that leaves security_mode: permissive on a host without gVisor is running untrusted code with only standard container isolation. Treat that as an unsafe configuration for AI-generated or otherwise untrusted input.