It was eleven at night when I pulled up the npm page for the community node my client had installed three months before I started working with them. I wasn’t looking for anything specific. I was doing what I always do before signing off on someone else’s n8n instance: reading the source of anything that hadn’t shipped from the n8n core team.

The node had four hundred weekly downloads and a clean install history. GitHub repo with eleven stars. README that showed a demo workflow, a usage section, a list of supported operations. Looked fine. Looked like the kind of thing someone builds on a weekend because the official node doesn’t support a specific API response format and they needed it to work.

The index.js was three hundred and twelve lines. I got to line two hundred and forty-seven before I found the fetch call that shouldn’t have been there.

It was not subtle once you saw it. A POST request, triggered on every node execution, sending a payload to an endpoint I didn’t recognise. The payload included this.getCredentials(), which in n8n’s node execution context returns the decrypted credential object. Not a token ID. The actual decrypted OAuth tokens, API keys, whatever the node had been given access to during the workflow execution.

I called my client at eleven thirty on a Tuesday. He picked up, which I appreciated. We rotated every credential on that n8n instance before midnight.

This is the thing the documentation explains without actually explaining. The n8n docs say community nodes “have access to the same capabilities as built-in nodes” and that you should “only install community nodes from trusted sources.” Both statements are technically true. Neither tells you that a community node executing inside your n8n instance has access to your decrypted credentials during that execution, that there is no sandboxing at the node level, no network policy enforced on what the node can call independently of your workflow logic, and no audit of outbound requests a node makes on its own behalf.

The n8n process runs with whatever permissions you gave it on your host. Community nodes run inside that process. A community node that calls this.getCredentials() and sends the result to an external server is doing something your workflow never asked it to do, and nothing in n8n will flag it. The execution log shows the node ran successfully. Green tick. Everything looks fine.

Image credit: Screenshot from “I’ve Been Using the n8n MCP WRONG – The Correct Workflow” by AI LABS on YouTube (https://www.youtube.com/watch?v=jUfpYmN9q6Y).

This is not a theoretical attack surface. The npm ecosystem has been through this pattern enough times that it should be a known risk category by now. Malicious packages that look legitimate, download counts padded by automated installs, README files that copy structure from the real library they’re impersonating. The n8n community node registry is npm. That is all it is. There is no additional vetting layer, no credential access disclosure requirement, no automated scanning for suspicious outbound requests in published packages before they reach your instance.

Make.com, for what it’s worth, doesn’t have this specific problem because it doesn’t have community-built execution modules in the same sense. What Make.com does have is a different kind of limitation: you are locked into what Make provides, and when a module doesn’t support what you need, your options are an HTTP module workaround or a feature request that closes as “under consideration” six months later. That is its own frustration and I have had it plenty of times mid-client-project. But the trust boundary is cleaner. The code running your automations is Make’s code. You didn’t install it from npm at midnight because someone in a Discord server said it fixed the thing you needed fixed.

The n8n team’s position, as far as I can read from the documentation and the GitHub discussions, is that community nodes are an ecosystem choice made by the user and the responsibility for vetting sits with the user. That is a reasonable position in theory. In practice, most people installing community nodes are doing it because they need something to work right now, and reading three hundred lines of JavaScript at line two hundred and forty-seven is not something most users are going to do before clicking install.

After that incident I added a step to every n8n instance review I run: pull the source of every community node, grep for getCredentials and outbound fetch or axios calls that aren’t documented in the README, and check the npm publish history for silent updates after the initial release. A silent patch update on a community node, two weeks after initial publish, with no changelog entry, is a specific shape of thing I now treat as a reason to read the diff before I let it run anywhere near production credentials.

That is not a workflow any user should have to build for themselves. It is a gap in the platform’s security model described as user responsibility, which is a common way to ship a gap without calling it one.

If you are running n8n with community nodes installed, go read the actual source of each one. Not the README. The source. You may find nothing wrong. I hope you do. But “I hope you do” is not a security posture, and right now it is more or less what the ecosystem is offering you.

Share.

Olaitan Oladipo holds a BSc in Sociology from Olabisi Onabanjo University. He is a self-taught automation builder who has spent years inside n8n doing the work that most tutorials skip: debugging OAuth errors at 2am, migrating client automations from Make.com mid-project, fighting reverse proxy misconfigurations on AWS EC2, and figuring out through trial and error what actually holds up in production versus what only looks clean in a demo. He is not a developer by training and not a SaaS founder. He is the person in the Discord server who actually answers the question instead of linking to the docs. His writing on n8n Automation Tutorial covers self-hosting, AI agent workflows, tool comparisons, and the security vulnerabilities the automation industry would rather not discuss. He has built AI-assisted invoice approval flows using OpenAI function calling, connected Claude via HTTP Request nodes, and holds considered opinions about Zapier, Make.com, LangChain, and CrewAI that their marketing teams would not appreciate. He writes for people who are technical enough to follow a tutorial but experienced enough to want the honest version.

Leave A Reply

Exit mobile version