N8n 2.0 Python Code node blocks all imports (stdlib & external) – how to configure permissions?

TL;DR:
After upgrading to n8n 2.0.2, the Python Code node blocks all imports — including standard library modules (re, urllib) and external packages (bs4).
Running n8n via Docker on an Ubuntu VPS.
Looking for a step-by-step solution to configure permissions or a recommended workaround.

Describe the problem/error/question

After upgrading to n8n 2.0.2, my Python Code node is no longer able to import any modules.
It fails even for standard library imports like re and urllib.parse, and also blocks external packages like bs4.

I run n8n on a Hostinger VPS (Ubuntu) via Docker. This used to work before the upgrade.

I’m looking for a step-by-step guide to enable Python imports in the new sandbox/security model (at least stdlib, and ideally allow specific external packages like beautifulsoup4).
I’m not very experienced with VPS/Docker, so a clear explanation is important.

Also, if this requires a different deployment approach (custom image with packages, config flags/env vars, or a separate Python service), I’d appreciate guidance.

What is the error message (if any)?

Security violations detected
Line 1: Import of external package ‘bs4’ is disallowed. Allowed external packages: none
Line 2: Import of standard library module ‘re’ is disallowed. Allowed stdlib modules: none
Line 3: Import of standard library module ‘urllib.parse’ is disallowed. Allowed stdlib modules: none

Stack trace

Error: Security violations detected
at throwExecutionError (…/n8n-nodes-base/nodes/Code/throw-execution-error.ts:11:9)
at PythonTaskRunnerSandbox.runUsingIncomingItems (…/n8n-nodes-base/nodes/Code/PythonTaskRunnerSandbox.ts:57:30)
at processTicksAndRejections (node:internal/process/task_queues:105:5)
at ExecuteContext.execute (…/n8n-nodes-base/nodes/Code/Code.node.ts:171:12)
at WorkflowExecute.executeNode (…/n8n-core/src/execution-engine/workflow-execute.ts:1045:8)
… (full trace available if needed)

Please share your workflow

Minimal reproduction is a single Python Code node with:

from bs4 import BeautifulSoup
import re
from urllib.parse import urlparse

(full exported workflow JSON available if needed.)

Share the output returned by the last node

No output – node fails immediately with the security violation error above.

Information on your n8n setup

  • n8n version: 2.0.2

  • Database: Not sure (might be default SQLite)

  • n8n EXECUTIONS_PROCESS setting: Not sure (default)

  • Running n8n via: Docker

  • Operating system: Ubuntu (Hostinger VPS)

What I need / questions

  1. Is there a supported way in n8n 2.x to allow stdlib imports (e.g., re, urllib.parse) in the Python Code node?

  2. Can I allowlist specific external packages (e.g., beautifulsoup4) and how? (env vars / config / docker flags?)

I’m also open to paid hands-on help (remote session) if someone from the community offers consulting, because this is blocking part of my business.

Thanks!

i have the same problem (n8n-Setup: Docker, Hostinger)

Problem: After upgrading to n8n 2.1.1, Python code nodes fail with security violations when importing standard library modules like re:

Security violations detected
Line 1: Import of standard library module ‘re’ is disallowed. Allowed stdlib modules: none

Even basic Python code fails:
python
import re
print(“ok”)

Current Setup

Docker Compose Configuration:

n8n service:
yaml
n8n:
image: n8nio/n8n:2.1.1
environment:

  • N8N_RUNNERS_ENABLED=true
  • N8N_RUNNERS_MODE=external
  • N8N_RUNNERS_AUTH_TOKEN=mein_geheimnis_123
  • N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0

task-runners service:
yaml
task-runners:
build: .
container_name: stack-n8n-runners
environment:

  • N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
  • N8N_RUNNERS_AUTH_TOKEN=mein_geheimnis_123
  • N8N_PYTHON_ALLOW_BUILTINS=*
  • N8N_PYTHON_ALLOW_STDLIB=*
  • N8N_PYTHON_ALLOW_EXTERNAL=*
  • NODE_FUNCTION_ALLOW_BUILTIN=*
  • NODE_FUNCTION_ALLOW_EXTERNAL=*
    command: [“javascript”, “python”]

Dockerfile for task-runners:
dockerfile
FROM n8nio/runners:2.1.1
USER root
RUN cd /opt/runners/task-runner-python &&
uv pip install --python .venv/bin/python beautifulsoup4 &&
chown -R runner:runner /opt/runners/task-runner-python
USER runner

What I’ve Tried

  1. :white_check_mark: Task runners are successfully registered and connected:

    Registered runner “launcher-python” (5d2e0c86689d007e)
    Registered runner “launcher-javascript” (e641d0d7006776df)

  2. :white_check_mark: Runners are waiting for tasks:

    [launcher:py] Waiting for launcher’s task offer to be accepted…
    [launcher:js] Waiting for launcher’s task offer to be accepted…

  3. :cross_mark: Setting various environment variables for permissions (tried in both n8n and task-runners):

    • N8N_RUNNERS_STDLIB_ALLOW=*
    • N8N_RUNNERS_EXTERNAL_ALLOW=*
    • N8N_PYTHON_ALLOW_STDLIB=*
    • N8N_PYTHON_ALLOW_EXTERNAL=*
    • PYTHON_RUNNER_ALLOW_STDLIB=*
    • N8N_BLOCK_RUNNER_ENV_ACCESS=false
  4. :cross_mark: Tried using config file approach (JSON config was not read properly by the runner)

Questions

  1. What is the correct environment variable name to allow stdlib imports in external Python runners for n8n 2.1.1?
  2. Should these permissions be set in the n8n container or the task-runners container?
  3. Is there additional configuration needed in the Python runner sandbox to allow standard library imports?

System Info

  • n8n version: 2.1.1 (self-hosted)
  • Task runners: n8nio/runners:2.1.1
  • Setup: Docker Compose with external mode
  • The runners connect successfully but all Python stdlib imports are blocked

Any help would be greatly appreciated!

My asnwer was for anoterh version…. sry
have to try it in this version and figure it out with thus sidecar and runnners….

You need to setup the n8n-task-runners.json file and do permissions inside there (env-overrides section). Take a look here.

1 Like

So, I also struggled with this issue last 1-2 weeks ago managed to fix it already.

It’s really matter on how you’re delivering configuration file into your local n8n workflow app that you are hosting on Docker (Probably), right now.

I’d recommend you to build the Dockerfile along with Docker Compose so that way it’s more structured and uncomplicated to fix and configure after on, below is a step-by-step on how to build n8n app local with three components Dockerfile, docker-compose.yaml and n8n-task-runners. json

Step 1: Folder Structure

  • Your_Project_Folder/
    • Dockerfile

    • docker-compose.yaml

    • n8n-task-runners.json

Step 2: Files & Configuration

  • What should be inside a Dockerfile?
    • FROM n8nio/runners:latest # I’m currently using latest
      
      USER root
      
      RUN cd /opt/runners/task-runner-javascript && pnpm add moment uuid
      
      RUN cd /opt/runners/task-runner-python && uv pip install beautifulsoup4 #Ur desired lib
      
      COPY n8n-task-runners.json /etc/n8n-task-runners.json
      
      USER runner
      
  • What should be inside docker-compose.yaml?
    • version: ‘3.8’
      
      services:
      
      n8n:
      
      image: n8nio/n8n:latest
      
      container_name: n8n_server
      
      environment:
      
        - N8N_RUNNERS_ENABLED=true
      
        - N8N_RUNNERS_MODE=external
      
        - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
      
        - N8N_RUNNERS_AUTH_TOKEN=password1234
      
        - N8N_NATIVE_PYTHON_RUNNER=true
      
        - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false
      
      ports:
      
        - "5678:5678"
      
      volumes:
      
        - ./n8n_data/.n8n:/home/node/.n8n # Add ur own storage folder, If u have one if not it will create news.
      
      restart: always
      task-runners:
      
      build:
      
        context: .
      
        dockerfile: Dockerfile
      
      container_name: n8n-runners
      
      environment:
      
        - N8N_RUNNERS_TASK_BROKER_URI=http://n8n_server:5679
      
        - N8N_RUNNERS_AUTH_TOKEN=password1234
      
        \# etc.
      
      depends_on:
      
        - n8n
      
      restart: always
      
  • What should be inside n8n-task-runners.json?
    • {
      
      "task-runners": \[
      
          {
      
              "runner-type": "javascript",
      
              "workdir": "/home/runner",
      
              "command": "/usr/local/bin/node",
      
              "args": \[
      
                  "--disallow-code-generation-from-strings",
      
                  "--disable-proto=delete",
      
                  "/opt/runners/task-runner-javascript/dist/start.js"
      
              \],
      
              "health-check-server-port": "5681",
      
              "allowed-env": \[
      
                  "PATH",
      
                  "GENERIC_TIMEZONE",
      
                  "NODE_OPTIONS",
      
                  "N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
      
                  "N8N_RUNNERS_TASK_TIMEOUT",
      
                  "N8N_RUNNERS_MAX_CONCURRENCY",
      
                  "N8N_SENTRY_DSN",
      
                  "N8N_VERSION",
      
                  "ENVIRONMENT",
      
                  "DEPLOYMENT_NAME",
      
                  "HOME"
      
              \],
      
              "env-overrides": {
      
                  "NODE_FUNCTION_ALLOW_BUILTIN": "crypto",
      
                  "NODE_FUNCTION_ALLOW_EXTERNAL": "moment",
      
                  "N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST": "0.0.0.0"
      
              }
      
          },
      
          {
      
              "runner-type": "python",
      
              "workdir": "/home/runner",
      
              "command": "/opt/runners/task-runner-python/.venv/bin/python",
      
              "args": \["-m", "src.main"\],
      
              "health-check-server-port": "5682",
      
              "allowed-env": \[
      
                  "PATH",
      
                  "N8N_RUNNERS_LAUNCHER_LOG_LEVEL",
      
                  "N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
      
                  "N8N_RUNNERS_TASK_TIMEOUT",
      
                  "N8N_RUNNERS_MAX_CONCURRENCY",
      
                  "N8N_SENTRY_DSN",
      
                  "N8N_VERSION",
      
                  "ENVIRONMENT",
      
                  "DEPLOYMENT_NAME"
      
              \],
      
              "env-overrides": {
      
                  "PYTHONPATH": "/opt/runners/task-runner-python",
      
                  "N8N_RUNNERS_STDLIB_ALLOW": "", #Add your desired stdlib, If u have.
      
                  "N8N_RUNNERS_EXTERNAL_ALLOW": "beautifulsoup4" #Add your desired extlib, If u have make sure to add it into pip install section in a Dockerfile.
      
              }
      
          }
      
      \]
      
      }
      

Step 3: Build your container

  • Basically, here u builds your container using the docker build command.

I hope all of this material might possible somehow clarifying u out on how to properly install an external and internal lib for using on Python node, this is my first post here if it’s making some confusing, I’m apologies.

Don’t hesitate to ask me for any further clarification and remove all of my # comment before build up your container.

2 Likes

Hi @Natthaphong_Chaudier,

Thank you so much for your tips! Your suggestion to use a custom n8n-task-runners.json was the absolute game-changer for me.

Before implementing your advice, I was constantly running into “Virtual environment missing” and chdir errors in the logs. It turns out the task-runners in v2.1.1 are very sensitive regarding their working directories and port assignments.

For anyone else struggling with this, here is the final setup that worked for me based on Natthaphong’s input:

1. The n8n-task-runners.json (The key to success)
By defining explicit working-directory paths and unique health-check-server-ports (5681, 5682), the port conflict with the launcher (default 5680) was resolved.

{
  "task-runners": [
    {
      "runner-type": "javascript",
      "working-directory": "/opt/runners/task-runner-javascript",
      "health-check-server-port": "5681",
      "env-overrides": {
        "NODE_FUNCTION_ALLOW_BUILTIN": "*",
        "NODE_FUNCTION_ALLOW_EXTERNAL": "moment,uuid"
      }
    },
    {
      "runner-type": "python",
      "working-directory": "/opt/runners/task-runner-python",
      "command": "/opt/runners/task-runner-python/.venv/bin/python",
      "args": ["-m", "src.main"],
      "health-check-server-port": "5682",
      "env-overrides": {
        "PYTHONPATH": "/opt/runners/task-runner-python",
        "N8N_RUNNERS_STDLIB_ALLOW": "*",
        "N8N_RUNNERS_EXTERNAL_ALLOW": "bs4,beautifulsoup4"
      }
    }
  ]
}

2. The Dockerfile
I used uv pip to inject my custom libraries into the runner’s internal virtual environment:

FROM n8nio/runners:2.1.1
USER root
RUN cd /opt/runners/task-runner-python && \
    uv pip install --python .venv/bin/python beautifulsoup4
COPY n8n-task-runners.json /etc/n8n-task-runners.json
RUN chown runner:runner /etc/n8n-task-runners.json
USER runner

3. docker-compose.yml
Ensure you use the correct variable name N8N_RUNNERS_CONFIG_FILE to point to the JSON.

Everything is running smoothly now, and the “Security Violation” errors in the UI are gone. Thanks again for pointing me in the right direction!

1 Like

@FriLa You’re welcome, I’m glad that a part of my suggestion could help you experiences better on n8n. Enjoy and hope all the best for you!

Hello, I have the message “Security violations detected” on self-hosted n8n version 2.0.2 with runner (version latest or 2.1.1). Native python works. When i add n8n-task-runners.json file, i have a time outon node execute Native python. Ther is a conflict I think. Could you put the compose.yaml (service n8n and runner) with all the necessary variables. Thanks a lot.

1 Like