Feb 27, 2026·6 min read·34 visits
The Zendesk Trigger node in n8n failed to verify webhook signatures, allowing anyone with the webhook URL to spoof events. Attackers could trigger workflows with fake data. The fix introduces HMAC verification, but users must manually toggle workflows to fetch the signing keys.
A critical oversight in the n8n Zendesk Trigger node allowed attackers to forge incoming webhooks, bypassing authentication completely. By ignoring the cryptographic signature provided by Zendesk, n8n accepted any HTTP POST request to the webhook URL as a legitimate event. This vulnerability highlights the dangers of implicit trust in webhook endpoints and requires a manual intervention—deactivating and reactivating workflows—even after patching.
Automation platforms like n8n are the glue of the modern internet. They take data from Service A (Zendesk), massage it, and shove it into Service B (Slack, Jira, Postgres). It's magic, until it's black magic.
The Zendesk Trigger node is designed to sit passively, waiting for Zendesk to shout "New Ticket!" or "Ticket Updated!" via a webhook. Webhooks are essentially public HTTP endpoints. Because they are public, the standard security model relies on a "shared secret" handshake. Zendesk signs the payload, and the receiver (n8n) checks the signature.
But what happens when the receiver is too polite to check credentials? You get GHSA-38C7-23HJ-2WGQ. In affected versions of n8n, the Zendesk Trigger node was operating on the "honor system." It assumed that if a request arrived at the specific UUID-generated URL, it must be from Zendesk. It’s the digital equivalent of unlocking your front door just because someone knocked.
Zendesk, being a responsible platform, includes a header in its webhook requests: X-Zendesk-Webhook-Signature. This is an HMAC-SHA256 hash of the timestamp and the request body, signed with a secret key known only to Zendesk and the integration owner.
The vulnerability here wasn't a complex buffer overflow or a heap grooming exploit. It was a simple logic omission. The code responsible for handling the incoming trigger looked something like this (conceptually):
Notice the missing step? It never validated the X-Zendesk-Webhook-Signature. The node blindly trusted the input. This falls under CWE-345 (Insufficient Verification of Data Authenticity). If an attacker guessed, leaked, or brute-forced the webhook URL—which is often just a UUID—they could send any JSON payload they wanted. n8n would happily ingest it and pass it down the pipeline as trusted data.
The patch, introduced in commit 3839e310bd4c3002c646c363d1411916fa195151, reveals exactly how the developers closed the hole. They had to introduce a mechanism to fetch the signing secret and then use it to validate requests.
First, they added a helper to compute the HMAC:
function verifySignature(signature: string, timestamp: string, body: string, secret: string): boolean {
const hmac = crypto.createHmac('sha256', secret);
const data = timestamp + body;
const digest = hmac.update(data).digest('base64');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}> [!NOTE]
> Notice the use of crypto.timingSafeEqual. This prevents timing attacks where an attacker could guess the signature byte-by-byte by measuring how long the comparison takes.
However, the most interesting part of the patch is the fail-open mechanism for backward compatibility. Look at this logic in the trigger handler:
// If we don't have a secret, we can't verify, so we let it through
// to avoid breaking existing workflows that haven't been reactivated.
if (!webhookSecret) {
return true;
}This is a critical nuance. The code only verifies the signature if webhookSecret exists in the workflow's static data. This secret is only fetched when the node is activated (setup). This means patching the software is not enough to stop the exploit. Old workflows remain vulnerable until manually reset.
Let's assume we are the attacker. Our goal is to trigger an internal business process defined in n8n. Perhaps the workflow creates a Jira ticket or sends a Slack message when a "High Priority" Zendesk ticket arrives.
Step 1: Reconnaissance
We need the webhook URL. These often leak in client-side code, GitHub repos, or browser history. They look like https://n8n.corp.com/webhook/5f8b9....
Step 2: Crafting the Payload We don't need to sign anything. We just need to match the JSON structure the workflow expects. A standard Zendesk payload might look like this:
{
"ticket": {
"id": 1337,
"priority": "urgent",
"subject": "URGENT: Refund $50,000 to Attacker",
"description": "Authorized by CEO."
}
}Step 3: Execution We send the request using standard tools. No complex headers required, just the content type.
curl -X POST https://n8n.target.com/webhook/uuid-1234-5678 \
-H "Content-Type: application/json" \
-d '{"ticket": {"id": 999, "priority": "urgent", "subject": "pwned"}}'The n8n instance processes this as a valid event. If the workflow has logic like if (ticket.priority === 'urgent') send_slack_alert(), that alert fires. If it has logic like update_database(), the database is corrupt.
Why is this severity only "Moderate" (5.0)? It comes down to the Attack Complexity (AC:H). The attacker needs the specific Webhook URL. Unlike a standard RCE where you hit the root domain, this requires knowledge of a GUID.
However, once that URL is known, the impact can be severe depending on the workflow logic:
It turns the automation platform into a proxy for the attacker, bypassing internal firewalls because the requests originate from the trusted n8n server.
To mitigate this, you must update n8n to version 1.123.18, 2.6.2, or higher. But as mentioned in the code analysis, updating is only half the battle.
The Critical Step: Manual Reactivation Because the fix logic is "fail-open" (to prevent breaking legacy setups), the node will only enforce signature verification if it has fetched the signing secret from Zendesk. This fetch happens during the node's activation phase.
When you reactivate, n8n makes an API call to Zendesk: GET /webhooks/{id}/signing_secret. It stores this secret. Only then does the verifySignature logic kick in. If you skip this step, you are still vulnerable, even on the latest version.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
n8n n8n | < 1.123.18 | 1.123.18 |
n8n n8n | >= 2.0.0, < 2.6.2 | 2.6.2 |
| Attribute | Detail |
|---|---|
| Attack Vector | Network (Webhook Endpoint) |
| CVSS | 5.0 (Moderate) |
| CWE | CWE-345 (Insufficient Verification) |
| Exploit Status | PoC Available |
| Complexity | High (Requires URL knowledge) |
| Privileges Required | None |
A local security vulnerability in the Nuxt development server (nuxt dev) allows local unprivileged users to access sensitive configuration files and source code. On Linux environments running Node.js 20+, Nuxt bound its internal vite-node IPC server to an abstract-namespace Unix socket without any peer authentication, enabling co-resident local users to connect and request module code directly.
Mozilla Bleach is an open-source HTML sanitizing library for Python. Versions up to and including 6.3.0 contain an incomplete filtering implementation in the URI validation logic ('sanitize_uri_value'). This logic fails to detect disallowed protocols, such as 'javascript:', if they contain Unicode invisible characters, whitespace characters, or characters with a code point greater than U+00A0. While standard-compliant web browsers do not directly execute invalid URI schemes containing these non-standard characters, downstream systems that normalize Unicode text by stripping invisible or non-ASCII characters can unintentionally reactivate the 'javascript:' prefix, causing Cross-Site Scripting (XSS). Additionally, this behavior violates Bleach's core sanitization contract by outputting URIs that bypass protocol allowlists configured by the caller.
An uncontrolled resource consumption vulnerability exists in the Python package Bleach when parsing text to linkify email addresses. When `parse_email=True` is enabled, the regular expression engine is forced into a quadratic-time complexity scan on specially crafted payloads lacking an '@' symbol. This causes immediate CPU exhaustion and blocks application server worker processes.
A path traversal and sandbox escape vulnerability in LangChain and LangChain-Anthropic Python packages allows unauthenticated local attackers to access files outside the restricted directory via crafted input, symbolic links, or prefix bypasses.
The PHP Secure Communications Library (phpseclib) contains a Server-Side Request Forgery (SSRF) vulnerability due to an insecure default implementation of Authority Information Access (AIA) certificate chasing. This flaw allows remote, unauthenticated attackers to coerce applications validating user-supplied X.509 certificates into generating arbitrary outbound HTTP requests to internal networks or local interfaces.
A directory traversal vulnerability exists in the Microsoft .NET System.Formats.Tar library during archive extraction. When extracting a TAR archive using the TarFile.ExtractToDirectory API, the extraction engine improperly resolves symbolic links prior to file creation, allowing local unauthorized attackers to write or overwrite arbitrary files outside the target directory. This can lead to local tampering, privilege escalation, or arbitrary code execution.