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.

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/workflowsreturns full workflow definitions, including any JavaScript or Python code and secrets hard-coded inside node parameters.GET /api/v1/executions?includeData=truereturns execution history with complete input and output payloads.GET /api/v1/credentialslists 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-tablesexpose 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
.envfile with bothN8N_URLandN8N_API_KEY— their canonical example. N8N_MCP_URLorN8N_WEBHOOK_BASE_URLsitting next to a key.- Claude Code permission files —
.claude/settings.jsonor.claude/settings.local.json— that embed a full curl command with theX-N8N-API-KEYheader inline. Those files do not get the.gitignoreprotection that.envfiles 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:
- Delete the leaked key in n8n under Settings, then API, then API Keys.
- 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.
- Rotate
N8N_ENCRYPTION_KEYif there is any chance the instance config leaked. It is the master key for every stored credential. Generate a new one withopenssl rand -hex 32and 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. - 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.
- 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_KEYexplicitly 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 aPOST /api/v1/auditendpoint. 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.gitignorebefore 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.