I have a confession that will probably get me a knowing nod from every sysadmin in the room: I once committed a real API key to a GitHub repository and only caught it because a teammate’s scanning tool flagged the commit. The service had been decommissioned by then, so the damage was zero. But the habit of shipping credentials into git history is exactly what GitGuardian just documented on a much larger scale with n8n — and the blast radius is a lot bigger than I assumed.

Server rack with hard drives and network cables in a data center, illustrating n8n automation infrastructure security
Image: Federal Bureau of Investigation via Wikimedia Commons (Public Domain)

What GitGuardian found

GitGuardian’s researchers scanned public GitHub commits for n8n API tokens and turned up 4,576 unique credentials tied to 1,255 hostnames. Of the 896 instances they could reach at test time, 321 accepted at least one of the leaked tokens — roughly 36 percent of the reachable ones, and about a quarter of every hostname they identified. Staff researcher Guillaume Valadon published the details on The Hacker News this week.

Here is the part that should bother anyone running an automation server: none of those 321 instances was hacked in the classic sense. No exploit, no CVE, no zero-day. A credential that someone had committed to a public repository was simply still valid, and the platform accepted it as if the owner had typed it in.

Why an n8n token is worse than most tokens

n8n sits between your systems. Workflows connect databases, source control, cloud accounts, AI services, and support tools, and each connection stores a credential. A leaked n8n API key — a signed JWT with an "aud": "public-api" claim — can read all of that context:

  • GET /api/v1/workflows returns full workflow definitions, including any JavaScript or Python code and secrets hard-coded inside node parameters.
  • GET /api/v1/executions?includeData=true returns execution history with complete input and output payloads.
  • GET /api/v1/credentials lists every stored credential object, and with enough privilege an attacker can create workflows that make n8n use those credentials — or even ship them to an external endpoint as a Bearer token.
  • GET /api/v1/users, /api/v1/variables, and /api/v1/data-tables expose accounts, variables, and table rows.

GitGuardian reproduced all four of those techniques against a controlled instance using only documented REST calls. An attacker does not need to see your OpenAI key’s value to burn through your quota — they just need the instance to spend it for them.

There is also a timing problem. Older n8n API keys carry no exp claim at all, so a token committed to GitHub months ago can stay valid until someone deletes it. n8n introduced a 30-day default expiration in version 1.78.0 back in February 2025, but keys minted before that — or created without an expiry — do not benefit from it.

Step 1: Scan your Git history with gitleaks

The fastest way to find out whether you have a problem is to scan the history of every repo you have touched with gitleaks, an open-source secret scanner. I tested it against a demo repo that mimicked the exact mistake: a .env file with N8N_URL and N8N_API_KEY committed, then “fixed” by deleting the token and adding .env to .gitignore.

# install (macOS)
brew install gitleaks
# or grab the binary for your platform from the releases page

# scan the working tree AND history
gitleaks detect --source /path/to/repo

# scan full git history explicitly
gitleaks git --log-opts="--all" --source /path/to/repo

Here is the output from my demo repo. HEAD was completely clean — the token only existed in an old commit — and gitleaks still found it:

$ gitleaks detect --source /tmp/n8n-demo-repo
INF 2 commits scanned.
INF scanned ~228 bytes in 260ms
WRN leaks found: 1

The JSON report flagged it under the generic jwt rule, with the commit hash, file, and line number. Real n8n keys are JWTs, so they trip the same rule. For continuous coverage, GitGuardian’s public monitoring runs an n8n-specific detector over public sources and runs a disclosure program called Good Samaritan that notifies developers when their keys show up.

Run the scan across every repo — including the private ones. Private repos leak too, the moment they are shared with a contractor, mirrored to a public fork, or accidentally made public.

Step 2: Hunt for the telltale patterns

GitGuardian found that the instance URL is usually committed right next to the token, which makes the hunt simpler. Look for:

  • A .env file with both N8N_URL and N8N_API_KEY — their canonical example.
  • N8N_MCP_URL or N8N_WEBHOOK_BASE_URL sitting next to a key.
  • Claude Code permission files — .claude/settings.json or .claude/settings.local.json — that embed a full curl command with the X-N8N-API-KEY header inline. Those files do not get the .gitignore protection that .env files usually enjoy. If you let AI assistants hold credentials like this, the audit process in my AI coding tool data privacy guide is worth rereading — and the trust question is the same one I raised when vetting VS Code extensions before installing them.

A quick grep across your repos is a decent first pass:

grep -rn "X-N8N-API-KEY" --include="*.json" --include="*.env*" --include="*.yml" .
grep -rn "N8N_API_KEY\|N8N_MCP_URL" .

Step 3: Test a suspected token — read-only, and only on instances you own

If you find a token, the validation trick from the research is a single read-only request. Pass the key in the X-N8N-API-KEY header and hit the workflows endpoint:

curl -s -o /dev/null -w "%{http_code}\n" \
  -H "X-N8N-API-KEY: <token>" \
  https://your-n8n.example.com/api/v1/workflows

I ran this against a local test instance to confirm the semantics. A valid key returns 200 with the workflow list, a garbage token returns 401, and a missing header returns 401. A 404 usually means the public API is disabled on that instance, which is the outcome you actually want. Only run this against infrastructure you own or are authorized to test — this exact command is how attackers enumerate, so do not aim it at anyone else’s server.

Step 4: Rotate, don’t just delete

Deleting the exposed key is the first move, not the last. Work through this list:

  1. Delete the leaked key in n8n under Settings, then API, then API Keys.
  2. Create a fresh key with the minimum scopes it needs. The current API requires you to declare scopes and an expiration date — the same 30-day-expiry design the researchers traced back to version 1.78.0.
  3. Rotate N8N_ENCRYPTION_KEY if there is any chance the instance config leaked. It is the master key for every stored credential. Generate a new one with openssl rand -hex 32 and re-enter your credentials through the UI so they are re-encrypted. If you lose this key, every stored credential is gone with it — back it up somewhere separate from the database.
  4. Open every workflow definition and look for hard-coded secrets. GitGuardian found a real workflow that backed itself up to a public GitHub repo with an SSH deployment key embedded in a node. Move those values into n8n’s credential store.
  5. Rotate any downstream credentials the leaked token could have reached — database passwords, cloud keys, AI API keys. Secrets that outlive their usefulness are how wallets get drained, as the 89 million dollar Coldcard heist demonstrated in brutal fashion.

Step 5: Harden the instance so a single key cannot do this

The research carries a sobering stat: 58 percent of the instances scanned were running a version affected by at least one known advisory, and one of those — CVE-2025-68613, an expression injection rated 9.9 on the CVSS scale — sits in CISA’s Known Exploited Vulnerabilities catalog. Patch discipline is table stakes. On top of that:

  • Set N8N_ENCRYPTION_KEY explicitly on every node — workers must share the same key.
  • Enable authentication and two-factor authentication for your users. Never run with user management off.
  • Disable the public API if you do not use it (N8N_PUBLIC_API_DISABLED=true).
  • Put the instance behind a reverse proxy with TLS, and restrict admin access by IP allowlist. Webhook endpoints can stay public; the UI and the API do not need to be.
  • Redact execution data so full payloads are not persisted.
  • Run n8n’s built-in security audit — the CLI command is n8n audit, and there is also a POST /api/v1/audit endpoint. The report flags unprotected webhooks, risky and community nodes, missing security settings, and an outdated version. On my test instance the endpoint is owner-gated — a read-scoped key gets a 403 — which is exactly the behavior you want.

The official n8n security docs walk through all of this in one place, from SSL to SSO to execution redaction.

Step 6: Keep secrets out of git for good

Scanning once finds today’s leaks; a habit finds tomorrow’s. Three cheap guardrails go a long way:

  • Add .env, *.env.*, and your Claude Code permission files to .gitignore before the first commit, not after.
  • Run gitleaks as a pre-commit hook or in CI so a leaked key fails the build instead of shipping.
  • Turn on GitHub’s own secret scanning if you host on GitHub — it catches many token families before you ever hear about it from someone else.

This is the same discipline I covered in my supply chain security guide for npm packages and, more recently, in the Keyv npm worm checklist — the ecosystem keeps reminding us that a single trusted component or credential can carry an entire compromise.

The bottom line

GitGuardian’s numbers are not a story about n8n being insecure. They are a story about credentials being treated as if they expire by themselves. The fix is boring and completely within reach: scan your history, rotate what you find, harden the instance, and make the scan a habit. I learned that lesson after a teammate caught my own mistake. Save yourself the embarrassment and run the scan before someone else does.

Filed under Tech & Gadgets
Last Update: August 7, 2026 by Felix AlterEgo
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Newest
Oldest Most Voted