With tools like n8n or Make, you can build workflows, connect APIs, and ship automation in minutes.

But that same speed often hides a serious problem: security is left behind.

In this post, I will show how a very common misconfiguration in n8n can expose workflows to the internet, how those endpoints can be discovered, and why this becomes a real risk in production environments.

The problem: unauthenticated webhooks

n8n allows you to create webhook endpoints that trigger workflows via HTTP requests.

By default, these webhooks can be configured without authentication.

That means that anyone who knows the endpoint URL can trigger the workflow.

In many cases, users leave this configuration unchanged.

Even worse, while n8n sometimes generates random UUID-based paths, many users rely on community templates where webhook paths are human-readable. For example:

  • /webhook/generate_answer
  • /webhook/create_user
  • /webhook/send_email

At that point, the endpoint is no longer hard to guess.

And if the name reveals the purpose of the workflow, the attacker is no longer dealing with a black box.

A simple example

Let's create a basic workflow.

None

The workflow acts as a wrapper around ChatGPT. It receives a request, sends it to OpenAI using your API key, and returns the response.

We configure the webhook like this:

  • Path: generate_answer
  • Authentication: none (default)
None

Once the workflow is activated, the endpoint becomes publicly accessible:

https://poc-test-2026.app.n8n.cloud/webhook/generate_answer

At this point, anyone with the URL can trigger the workflow using your credits.

None

But depending on the workflow, it could be worse:

  • Triggering internal automations
  • Sending emails
  • Writing to databases
  • Interacting with third-party systems

Confirming exposed endpoints

If an attacker suspects a webhook path, they can validate whether it exists by sending requests and observing the response.

For example, using a tool like ffuf with a small wordlist:

ffuf -w wordlist.txt -u https://target.com/webhook/FUZZ -X POST -mc 200,405,401
None

If the endpoint exists, it will typically return a 200 response.

In this simple example, this works because we already know the endpoint name.

That is not realistic at scale.

So the next step is obvious: build a better wordlist.

Building a webhook wordlist from real workflows

One of the largest public collections of n8n workflows is:

https://github.com/Zie619/n8n-workflows

Each workflow is stored as a JSON file.

Inside these files, webhook nodes (type n8n-nodes-base.webhook) often include a default path parameter.

None

When users import these workflows, many keep the default configuration unchanged.

That means we can extract real webhook paths directly from these templates.

The process is simple:

  1. Parse all JSON workflow files
  2. Extract the path field from webhook nodes
  3. Aggregate them into a wordlist

I vibe-coded a small Python script to do exactly that ;)

To run the script, you first need to download all the JSON workflow templates and store them in a folder. In this example, we use a folder called workflows.

python audit_n8n_webhook_paths.py "workflows"

The script will parse all the JSON files, extract the webhook paths, and generate a .txt file. This file can be used directly as a wordlist in ffuf.

Example of the generated wordlist:

Some paths are UUIDs, but many are human-readable and predictable.

And even UUIDs are not secure if they are reused across deployments.

Finding targets

Now that we have a wordlist, we need targets.

One effective way to find self-hosted n8n instances is using Shodan and favicon hashes.

Every web app serves a favicon, and in many cases it is identical across all deployments of the same software. That makes it a reliable fingerprint.

Instead of searching by domain or IP range, you can search for servers that share the same favicon hash, effectively identifying instances of the same application at scale.

http.favicon.hash:-831756631
None

At the time of writing, this query returns more than 73,000 results.

To export the full list of IP addresses, use the Shodan CLI. Please note that this step requires Shodan credits.

shodan download n8n-servers "http.favicon.hash:-831756631"

Now you have both:

  • A list of potential targets
  • A realistic wordlist of webhook endpoints

That is enough to start testing exposure.

Important note: Only run tests against systems you own or have permission to assess. This post is for educational purposes.

Key takeaways

Here's how to protect yourself:

1. Always enable authentication

n8n supports multiple built-in authentication methods:

  • Basic auth
  • Header auth
  • JWT auth

You should always use one of these when exposing a webhook.

If you need stronger guarantees, especially for service-to-service communication, you can implement HMAC signature verification. This is not natively supported in n8n webhooks (see the community discussion: https://community.n8n.io/t/feature-proposal-hmac-signature-verification-for-webhook-node/223375), so it requires custom logic.

When building this, there are a few things you need to include:

  • Event ID or nonce to prevent duplicate requests
  • Timestamp validation to prevent replay attacks

This ensures that every request is legitimate and cannot be reused or forged.

2. Use a reverse proxy

Put your n8n instance behind a proxy like Nginx or Traefik.

This allows you to:

  • Hide internal infrastructure
  • Add rate limiting
  • Block malicious traffic
  • Implement a WAF

3. Do not rely on endpoint names

A path like /generate_answer is not security.

Even UUIDs can leak or be reused.

If you import a workflow template, never keep the default webhook path. Generate a new UUID or a sufficiently random string for your endpoint.

Treat the webhook path as a secret.

Final thoughts

Publishing a webhook feels like a small step.

In reality, it is exposing an API to the internet.

And every exposed API becomes part of your attack surface.

If you are building fast, make sure you are also thinking defensively.