Custom code execution security
How Retool sandboxes custom code across services and the container privilege requirements for each.
Retool runs user-written code in three sandboxed services: code-executor for workflow JavaScript and Python, js-executor for functions, and the agent sandbox for AI agent tasks. Each uses Linux kernel isolation mechanisms but differs in its privilege requirements.
The code-executor container executes arbitrary user-written code for custom JavaScript or Python libraries in workflows. Retool recommends running code-executor with sandboxing enabled, for flow safety and data security reasons. But Retool does support running without sandboxing enabled, as it requires privileged container access, which some organizations do not allow.
Privileged container access is commonly restricted by default and why Retool allows code-executor to run in unprivileged mode. Should this be the case, Retool recommends an exception be made so that Retool can run as a trusted product or framework. This will allow code-executor to safely manage your operational code.
Security, functionality, and usability
Retool follows three core philosophies when developing the self-hosted architecture: security, functionality, and usability.
| Priority | Description |
|---|---|
| Security | Protect systems and data with strong safeguards. |
| Functionality | Build powerful and flexible features. |
| Usability | Provide straightforward and low-friction experiences. |
Too much focus on one priority can be at the detriment of the others. Retool's approach is to always strike the right balance across all three.
Due to the potential impact that executing arbitrary code can have, Retool prioritizes security and functionality above usability. As such, Retool's architecture is built so that this custom code is executed in a secure, sandboxed environment but without arbitrary restrictions. This approach ensures that customers don't have to review and ensure that all custom code written by their users is free from bugs or malicious code.
Sandboxed environment with NsJail
Retool uses NsJail, a process isolation tool for Linux, to securely execute custom code. NsJail leverages Linux kernel features such as namespaces, control groups (cgroups), and seccomp-bpf syscall filters to isolate custom code from the rest of the system.
By doing so, NsJail is able to isolate the file system, restrict network access, and enforce CPU and memory limits to prevent any single workflow from impacting overall system stability.
Priviledged and unprivileged modes
Docker containers can be run in either unprivileged or privileged mode.
| Mode | Description |
|---|---|
| Unprivileged | If the container cannot run with --privileged, NsJail cannot apply its sandbox. In this case, custom code runs without Retool’s isolation safeguards, and you must fully trust all user-written code. |
| Privileged | In self-hosted Retool, the code-executor container is configured with Docker’s --privileged flag. This allows NsJail to configure the kernel features required for sandboxing. NsJail then executes user code inside a jailed process with reduced privileges. |
The code-executor container is configured to run in privileged mode by default. Retool only uses the minimum amount of elevated permissions necessary to implement sandboxing and relinquishes these once no longer required.
Only code-executor and js-executor support privileged mode. Code-executor runs in privileged mode by default; js-executor supports it as an alternative to the custom seccomp profile but is not configured this way by default. All other backend services operate without elevated permissions.
Retool strongly recommends that self-hosted organizations always use privileged mode unless there are specific reasons which prevent this.
Exceptions for using unprivileged mode
In some cases, it may not be possible for a self-hosted deployment instance to run code-executor in priviledged mode. For instance:
- Managed container orchestration environments, such as GKE Autopilot and AWS Fargate, do not allow the use of privileged containers.
- Kubernetes clusters with pod security policies can explicitly block privileged containers.
Retool provides customers with the option of running the container in unprivileged mode for these types of situations. When you configure code-exector to use unprivileged mode, however, many of the safeguards that sandboxing provide are no longer in place. This assumes that you fully trust all user-written custom code that is executed.
Risks of non-sandboxed custom code environment
A non-sandboxed environment should only be used if an organization can trust that all users will not write code that is either malicious or critically flawed.
| Risk Category | Examples |
|---|---|
| Data risks | Exfiltrating credentials or sensitive data to an external attacker; accessing or manipulating restricted data. |
| Account risks | Compromising or taking control of other user accounts. |
| Execution risks | Interfering with future code execution. Bugs or malicious code can cause unexpected or unstable results. |
| System risks | Damaging the deployment instance by deleting or modifying critical system files. Bugs in user code can also cause unintended damage, such as erroneous deletion of files or unpredictable outcomes. |
| External misuse | Coordinating targeted attacks using the deployment instance. |
Agent sandbox with gVisor
The agent sandbox service (introduced in Retool 4.0) uses gVisor rather than NsJail. gVisor is a user-space kernel that intercepts and handles syscalls from sandboxed workloads, providing strong isolation without requiring privileged container access.
Unlike code-executor, the agent sandbox does not support privileged mode. A custom Linux seccomp profile is the only supported configuration — there is no unprivileged fallback. The profile is published in the Helm chart at charts/retool/files/gvisor-seccomp.json.
Seccomp profile
The profile extends the default container seccomp allowlist with a small set of additional syscalls that gVisor requires. These are scoped to the specific operations gVisor and its networking component (pasta) need — no broad capability grants like CAP_SYS_ADMIN are required.
| Syscalls | Purpose |
|---|---|
clone, clone3, unshare, setns | Namespace creation and entry for gVisor and the pasta networking component |
sethostname | Sets hostname inside the namespace (cosmetic, avoids a warning) |
mount, umount2 | Filesystem setup for the sandbox (tmpfs, proc, bind mounts) |
pivot_root | Filesystem root isolation for the sentry and gofer processes |
ptrace | Thread initialization for the gVisor systrap platform |
Comparison across services
| code-executor | js-executor | agent sandbox | |
|---|---|---|---|
| Sandboxing mechanism | NsJail | NsJail | gVisor |
| Privilege requirement | Privileged mode (default) or unprivileged (reduced security) | Custom seccomp profile (recommended) or privileged mode | Custom seccomp profile only |
CAP_SYS_ADMIN required | Yes (privileged mode) | No | No |
| Can run without sandboxing | Yes (unprivileged mode, not recommended) | No | No |
Customers who run code-executor with a custom seccomp profile rather than privileged mode can apply the same approach to js-executor and the agent sandbox. All three services are compatible with clusters that restrict --privileged containers, provided the appropriate seccomp profile is applied.
js-executor
The js-executor service provides a sandboxed JavaScript execution environment for functions. Like code-executor, it uses NsJail, but unlike code-executor, there is no unprivileged fallback. js-executor always executes functions within an active NsJail sandbox.
Retool recommends a custom Linux seccomp profile for configuring js-executor. Privileged mode is also supported but not recommended. No CAP_SYS_ADMIN is required. The profile is published in the Retool Helm chart at charts/retool/files/nsjail-seccomp.json alongside the agent sandbox profile.