n8n Security: From Exploitation to Defense

#cybersecurity

Part 1: Security of n8n Agents: Vulnerabilities, Attack Vectors, and Protection

In n8n systems that use "agents" (Telegram bots, webhooks, Discord bots, etc.), a variety of attacks are possible due to improper input validation and insecure nodes. Real-world research has shown that past versions of n8n contained vulnerabilities such as authentication bypass, filter evasion, and path traversal.

We will now explore the main categories of attacks, their exploitation techniques, and defense strategies.


Remote Code Execution (RCE)

n8n provides nodes that allow executing arbitrary commands on the server — for example, the Execute Command node or Function/Code nodes. If an attacker can control input into these nodes, they may gain RCE capabilities. Additionally, unsafe usage of eval() in user-provided code could lead to arbitrary JavaScript execution.

Among real-world issues is the possibility of RCE via a fake file path using a zip-slip injection (documented in CVE-2023-27562).


Injection Attacks (SQL, XSS, etc.)

If input data from chat or webhook endpoints is directly inserted into queries or HTML, it can lead to injection attacks. A classic example is SQL injection, where a database query is constructed by concatenating strings with user-supplied input.

When using the Postgres node in n8n, parameterized queries can be used to prevent injections. However, in the MySQL node, parameterization is not yet available, so manual input escaping is required.

XSS injections are also possible if user-submitted data is displayed in the web interface or sent with HTML/Markdown enabled. Without proper sanitization of special characters (<, >, ", etc.), a malicious script may execute in another user’s browser.


Bypassing Filters and Authorization

Simple filters (based on keywords or user IDs) can often be circumvented. For instance, in a Telegram bot, commands usually start with /. An attacker might insert invisible Unicode characters (zero-width spaces, non-joiners, etc.) to disguise a command or part of a word.

Homoglyphs (characters that look similar but belong to different encodings) can also be used to bypass exact string matching. Furthermore, access restrictions based on users can be evaded: if the bot does not strictly validate user_id, anyone who discovers it (e.g., as seen in the well-known case of “n8n assistant” ) can begin sending commands.


Attacks on HTTP/Code Nodes

If a workflow accepts a URL from a user and passes it to an HTTP Request node, attackers can exploit this to perform Server Side Request Forgery (SSRF), making requests to internal networks or local files.

Path Traversal attacks are also known: in CVE-2023-27562, there was a bypass in the /rest/credential-translation endpoint that allowed reading files outside the permitted directory.

Similarly, code-execution nodes containing eval() statements are dangerous if external data enters them.


Token and Data Leaks

If a workflow mistakenly includes tokens or API keys in outgoing responses (e.g., sending them in a Telegram message or a webhook response), an attacker may steal these secrets. Likewise, intercepting HTTP traffic without TLS protection can expose sensitive credentials.

Below is a summary table of attack types

Type of Attack
Exploitation Method
Example Protection Measures

RCE (Remote Code Exec)

Through Execute Command/Function nodes: passing a controlled string for execution on the server.

Block or disable Exec/Code nodes, disallow eval() at runtime, and isolate processes.

SQL Injection

Injecting malicious SQL into query fields (e.g., inserting '; DROP ...; via messages).

Use parameterized queries, escape and validate all user input.

XSS Injection

Injecting HTML/JS into bot messages (Markdown/HTML) or the web interface.

Disable unnecessary HTML/Markdown rendering, escape special characters, and apply Content Security Policy (CSP) headers.

Filter/Authorization Bypass

Sending commands with invisible Unicode characters, deep-linking (/start payload), or spoofing user_id.

Validate user ID/username, restrict the list of allowed users/groups, and implement RBAC and 2FA.

SSRF / Path Traversal

Using the HTTP Request node with internal resource URLs or path traversal (../) in the request path.

Validate URLs (use a domain allowlist), and update n8n to a version with the CVE patch applied.

Token/Secret Leak

Exfiltration of tokens/API keys via incoming/outgoing data or logs.

Store tokens in environment variables or secure vaults, encrypt them at rest, avoid exposing them in responses, and use HTTPS.

Exploitation (Simulating an Attacker)

An attack typically begins with interaction with a Telegram bot or another n8n front-end, without access to the admin panel. The attacker may find a public bot link (or webhook endpoint) and send specially crafted requests. For example:

Via Telegram

Send various commands and texts to the bot, including through deep-links (t.me/<bot>?start=PAYLOAD) to pass data. It is worth checking whether the bot processes messages with Markdown/HTML — insert special characters like *, <code></code>, tags like <i>, <a>`, etc., to see if parsing errors or XSS occur. Unicode characters (zero-width space, non-joiner, etc.) help hide the content of a command, bypassing simple filters.

Via Webhook

If a Webhook node is used, the attacker can send a forged JSON request pretending to be from Telegram: with fields such as update_id, message, etc. This allows "faking" a message from any user of the bot. For example, include fields like from.id, text, etc., in the JSON and send it to the public webhook address.

Special Characters and Data Formats

The attacker tries entering unexpected characters (modified Unicode symbols, URL encoding, Base64, etc.) to break input validation. If the workflow includes conditional nodes (IF) based on text content, they can bypass them by slightly changing the string (replacing letters with similar ones, adding markers).

Testing Business Logic

For example, if the bot allows executing arbitrary code or queries, inject payloads such as ; DROP TABLE for SQL or payload) for JS. If the workflow accepts URLs from users, enter http://localhost/secret or file:///etc/passwd to test SSRF/LFI.

Examples of Tools

Frameworks like BotFuzzer exist for comprehensive vulnerability discovery in Telegram bots. It automatically enumerates bot commands and states (similar to DFS), uncovering untested logic paths. Fuzz-testing research shows these techniques are effective at detecting SQL injections and buffer overflows. In the context of n8n workflows, similar “fuzzers” can be built by sending random or malformed data to Telegram/Webhook and HTTP Request nodes.


Security Testing

For developers and security specialists, it is important to proactively test flows for resilience.

Attack Simulation

On a separate secure environment, simulate attacker messages. You can write automated tests simulating Telegram Bot API behavior or manually use tools like Postman/cURL for webhooks. Most importantly, ensure that no secrets (database queries, environment variables) leak into responses.

Logging Suspicious Activity

Set up logging of all incoming messages and responses. Log analytics (e.g., via ELK/Kibana) helps detect anomalous patterns — multiple processing errors, repeated failed commands, or attempts to access non-existent resources. This aligns with general monitoring recommendations: “regularly check logs for suspicious activity”.

Input Fuzz Testing

Targeted fuzzing helps discover validation flaws. For example, auto-generate random strings for Telegram message fields (texts, titles, JSON parameters). As noted in fuzz-testing reviews, this method effectively detects unexpected vulnerabilities. Ready-made frameworks like BotFuzzer or custom scripts can send different commands and symbols to the bot. It is also useful to manually review the use of Function/Code nodes — make sure they don’t run unknown data using eval().


Protection Measures

Finally, to minimize risks, the following measures are applied.

Filtering and Validating Messages

Sanitize and validate all incoming data. For example, if the bot should not accept HTML, remove </> tags from text. It’s important to escape special characters (convert < to &lt;, etc.). For SQL queries — mandatory parameterization. If user-provided JSON is possible, strictly validate it against a schema (JSON Schema) and prohibit dangerous keys. In Telegram bots, it makes sense to filter user_id and allow commands only from trusted users/groups (whitelist).

Secure Workflow Design

Avoid potentially dangerous nodes. n8n allows blocking nodes (Node Blocking), for example, Execute Command or Code, which run third-party code. If a Function node is still needed, make sure there is no eval inside. For calculations, prefer strongly typed operations (e.g., JSON templates instead of JS code). Also, do not use HTTP requests to variables obtained directly from the user without validation. Regularly update n8n: many known vulnerabilities (CVE-2023-27562, CVE-2023-27564, etc.) have been fixed in versions ≥0.216.1.

Access and Permission Restrictions

Implement a full authentication system. Use role-based access control and two-factor authentication. If the bot works in a group, enable private mode (to avoid receiving outside messages) or verify chat_id. When connecting webhooks, require a secret token (Webhook Token) so that outsiders cannot send requests. Limit the rights of the account under which n8n runs (for example, the Linux user n8n should not have root access).

Secret and Token Protection

Never store keys in plain text. n8n encrypts credentials on disk, so configure a reliable encryption key (Environment variable N8N_ENCRYPTION_KEY). Whenever possible, use external secret stores (HashiCorp Vault, AWS Secrets Manager). Never insert the bot token into message text or logs. Provide HTTPS for all requests (Telegram API, webhooks, etc.) — this will prevent token interception in the network.

Additional Measures

Apply rate limiting to incoming webhooks to prevent DoS and brute force attacks. Use Content Security Policy for the n8n web interface. Conduct periodic pentests: try to simulate known attackers (SQLi, SSRF, etc.) and check that they are blocked. This multi-layered protection (“defense in depth”) is the key to the security of automated agents.


Common Attacks on n8n

1. Attack via Publicly Exposed n8n Instances

How n8n instances are discovered

  • Shodan / Censys / ZoomEye internet scans Public n8n instances (especially on ports 5678, 80, 443) are indexed by search engines using queries like:

    http.title:"n8n"
    http.favicon.hash: -2032395573

    ⚠️ Even if you think your IP is "unknown", it can appear in Shodan within minutes after starting the server.

  • Searching for errors or headers A simple curl to an IP or domain:

    curl -I http://example.com

    May reveal headers like:

    x-powered-by: n8n

    Or template error pages that clearly identify n8n.

  • Domains with prefixes like n8n. or workflow. Domains like n8n.domain.ru, workflow.domain.com are often brute-forced via DNS.

  • Reverse IP lookup If your n8n runs on a VPS whose IP has appeared elsewhere (e.g., another site or service), attackers can look up associated domains and find n8n.


What an attacker can do

  • DDoS against your domain or IP Without protection, massive HTTP requests can easily crash n8n — especially on weak servers. Common targets: /webhook or /rest endpoints.

  • Brute-force or automated API fuzzing If the interface is exposed, bots can test hundreds of paths in seconds (/rest/executions, /rest/credentials, /rest/workflows) and try to extract data.

  • CVE-based vulnerability scanning Knowing it's n8n and its version, an attacker may exploit known vulnerabilities like:

    • CVE-2023-27562 (Path Traversal)

    • CVE-2023-27564 (Credential Leak)

    • And other critical issues

  • Automated exploitation via Docker misconfigurations If you've improperly exposed ports like 5678, 15672 (RabbitMQ), or 3306 (MySQL), attackers will find and access them.


How to Protect Yourself

1. Hide n8n from the public internet Do not expose port 5678 publicly! Use Nginx reverse proxy or Traefik:

  • Only allow 443 (HTTPS) externally

  • Internally route everything through 127.0.0.1:5678

  • Block direct IP access using iptables, ufw, or Docker network settings — allow only Cloudflare or your private network.

sudo ufw deny 5678
sudo ufw allow from 127.0.0.1 to any port 5678

2. Obfuscate your n8n domain Use non-standard subdomains like:

tgw12h3.workflow-core.net

instead of n8n.example.com.

It is highly recommended to use different domains if your main domain is already in use elsewhere.

Disable indexing:

  • Add to robots.txt:

    User-agent: *
    Disallow: /
  • Add to HTML meta tags:

    <meta name="robots" content="noindex,nofollow">

Use Cloudflare DNS — it hides real IPs when configured correctly.

3. Cloudflare Access / IP Whitelisting Protect your instance with Cloudflare Access or HTTP Basic Auth. Even if found, no one gets in without credentials.

Alternative: Use VPN (Wireguard, Tailscale) and keep the UI fully internal.

4. Monitoring & Honeypot Protection Use Fail2ban: automatically block IPs making repeated requests to /rest or /webhook.

Add honeypots:

  • Hidden fake webhooks that log and immediately ban IPs accessing them.

5. Keep n8n Updated! All known CVEs (up to 2024) are patched in n8n ≥0.216.1 Enable auto-updates or at least monitor the changelog regularly.


2. Data Leak via Public Telegram Bots Built on n8n

Take this example: a user on Reddit discovered that it was possible to find other people’s n8n bots in Telegram by searching for “n8n assistant”. It was then enough to send a message — and the bot would reply, exposing the owner’s private data (calendar events, meetings, email) to an anonymous stranger.

How it happened:

  • The bot was publicly accessible — no user_id whitelist was enforced.

  • Anyone could interact with it and receive responses.

  • There was no input filtering — the workflow first fetched data (e.g., calendar info), and only later checked permissions — but it was already too late.

Consequences:

  • Exposure of personal information (meetings, email addresses).

  • Potential leakage of internal tokens or API keys if included in responses.

Conclusion:

This case is real and highly serious. A bot, even without direct n8n vulnerabilities, can become a perfect vector for data leaks.


Community Response

In the Reddit discussion, users actively suggested a simple solution — adding an IF node at the beginning of the workflow:

if(user_id !== OWNER_ID) return { text: "Unauthorized" };

Alternatively, configure restrictions directly in the Node Trigger: accept messages only from specific chat_id or user_id

Other Methods

  • Filter by user_id (Whitelist)

1. Get Your Telegram User ID

The easiest way is to send any message to your bot and check the incoming data in the Telegram Trigger. You’ll see a block like this:

{
  "message": {
    "from": {
      "id": 123456789,
      "username": "your_username",
      ...
    }
  }
}

Note the id. This is your Telegram user ID.


2. Add an IF Node at the Start of the Workflow

Place it right after the Telegram Trigger node:

Condition Setup:

  • Value 1: {{$json["message"]["from"]["id"]}}

  • Operator: equal

  • Value 2: your user ID (e.g., 123456789)

Branches:

  • TRUE branch: continue with the workflow logic.

  • FALSE branch: send a message like “Unauthorized” or do nothing.


Alternative Method (Using JavaScript Function Node)

If you prefer more flexible access control:

const allowedUsers = [123456789]; // Your user ID
const sender = $json["message"]["from"]["id"];

if (allowedUsers.includes(sender)) {
  return [items];  // Allow the message
} else {
  return [];       // Block the message
}

Additional Protection

  • Disable group chats for your bot — otherwise, it can be added to groups where anyone can interact with it.

  • In Telegram BotFather, set the following commands:

/setprivacy → Enable
/setjoingroups → Disable
/setcommands → Only list necessary commands

This ensures your bot only responds to one-on-one messages and cannot be used in group chats.


Part 2 will be added upon completion of tests with MCP.


Last updated

Was this helpful?