Task Runners (Sandboxing)
Relevant source files
The following files were used as context for generating this wiki page:
Task Runners provide a secure, sandboxed environment for executing arbitrary code within n8n workflows. They isolate user-provided logic from the main n8n process to prevent security risks and resource exhaustion. This system primarily supports languages like JavaScript and Python, ensuring that complex algorithms or external library dependencies do not compromise the stability of the core application.
The architecture relies on a Task Broker to manage communication between the n8n main process and specialized runner instances. This separation ensures that even if a task crashes or attempts malicious activity, the impact is contained within the sandbox.
Sources: packages/task-runner/src/task-runner.ts, packages/cli/src/task-runners/task-broker/task-broker.service.ts
Core Architecture
The system uses a hub-and-spoke model where the TaskBrokerService orchestrates various task runners. It handles task registration, dispatching, and result retrieval.
The diagram above shows the relationship between the main n8n process and the sandboxed task runners managed by the broker.
Task Broker Service
The TaskBrokerService acts as the primary interface for the rest of the n8n application. It manages the lifecycle of tasks and ensures that requests are routed to the appropriate language-specific runner. It maintains a registry of active runners and monitors their health.
Sources: packages/cli/src/task-runners/task-broker/task-broker.service.ts
Language Runners
Individual runners, such as the Python task runner, implement the specific execution logic for a target language. These runners listen for tasks, execute the provided code using appropriate interpreters (e.g., python3), and return serialized results.
Sources: packages/task-runner-python/src/task_runner.py, packages/task-runner/src/task-runner.ts
Task Execution Flow
Execution begins when a node (like a Code node) requests a task run. The broker serializes the input data and code, then sends it to a waiting runner.
The sequence diagram illustrates the request-response cycle between the workflow engine and the isolated execution environment.
Data Serialization
Tasks are exchanged using JSON-compatible formats. Inputs include:
- The script/code to execute.
- The input items (JSON objects).
- Environment variables or context metadata.
Sources: packages/task-runner/src/task-runner.ts, packages/task-runner-python/src/task_runner.py
Security and Isolation
Sandboxing is enforced through multiple layers of protection to ensure system integrity.
Environment Restrictions
Task runners operate with restricted permissions. Code execution is often limited by:
- CPU/Memory Limits: Preventing a single script from consuming all system resources.
- Network Isolation: Blocking unauthorized outbound connections from within the sandbox.
- Filesystem Access: Restricting access to sensitive local directories.
Sources: packages/nodes-base/AGENTS.md, packages/@n8n/workflow-sdk/src/prompts/sdk-reference/sdk-language.ts
Native Node Preference
The project encourages using native nodes over custom code nodes for standard operations (like filtering or restructuring) because native nodes are more efficient and undergo stricter internal validation. Code nodes are reserved for complex multi-pass algorithms or logic that expressions cannot handle.
| Feature | Code Node (Sandbox) | Native Node |
|---|---|---|
| Execution Speed | Slower (Overhead) | Faster (Native) |
| Security | Sandboxed isolation | Built-in validation |
| Debugging | Log-based | Visual debugging |
| Use Case | Complex logic/Algorithms | Data mapping/Filtering |
Sources: packages/@n8n/workflow-sdk/src/prompts/sdk-reference/sdk-language.ts:160-175, packages/nodes-base/AGENTS.md:110-120
Implementation Details
Python Runner (task_runner.py)
The Python runner handles script execution via the standard Python interpreter. It processes incoming task payloads and wraps user code to provide access to input items.
Key functions in the Python environment:
run(): The main entry point for processing a single task.execute_script(): Invokes the interpreter on the provided code block.
Sources: packages/task-runner-python/src/task_runner.py
JavaScript Runner (task-runner.ts)
The JavaScript runner uses a similar pattern but leverages Node.js isolation techniques. It allows the execution of modern JavaScript while restricting access to dangerous global objects.
Sources: packages/task-runner/src/task-runner.ts
Summary
Task Runners provide a robust infrastructure for executing custom user logic safely. By combining a centralized Task Broker with isolated language-specific sandboxes, n8n ensures that users can extend workflow functionality without risking the stability of the hosting environment. Developers should prioritize native nodes for standard transformations and use Task Runners for high-complexity requirements that necessitate custom scripting.