Attackers are deploying bots through Node-RED editors with no login (CVE-2026-58115, Siemens IoT2050)

7 min read

How to fix CVE-2026-58115: upgrade SIMATIC IoT2050 Advanced to Industrial OS V4.3.4.1 or later. Anywhere else, turn on adminAuth in Node-RED's settings.js: one POST /flows to an editor with no login is enough to run a Linux bot, and VulnCheck saw it in the wild on October 30.

Attackers are deploying bots through Node-RED editors with no login (CVE-2026-58115, Siemens IoT2050)
On this page

Someone is sending one HTTP request to Node-RED editors that have no login, replacing whatever flows were running with three nodes that download a Linux bot and start it. VulnCheck caught the first one on a decoy on October 30, 2026. The bug it filed under is CVE-2026-58115, a CVSS 10.0 missing-authentication flaw that Siemens assigned to Node-RED on the SIMATIC IoT2050 Advanced gateway back in August.

The Siemens part is the narrow part. The request works against any Node-RED instance that runs without adminAuth, because that is how Node-RED ships. Its own security guide opens with: "By default, the Node-RED editor is not secured - anyone who can access its IP address can access the editor and deploy changes." If you run Node-RED on a Raspberry Pi, a VM, a container or a factory gateway, the check below applies to you.

How to fix

On a SIMATIC IoT2050 Advanced (article number 6ES7647-0BA00-1YA2), update Industrial OS to V4.3.4.1 or later from Siemens support entry 109741799. If you cannot update yet, Siemens lists two mitigations: uninstall Node-RED, or harden it using the Node-RED user guide. The advisory does not say what the new image changes, so run the login check below after the update too.

Everywhere else there is no package to upgrade. Moving to the newest node-red release does not add a password. You turn authentication on in settings.js in the Node-RED user directory (~/.node-red by default):

node-red admin hash-pw

That prints a bcrypt hash. Uncomment the adminAuth block in settings.js and put the hash in:

adminAuth: {
    type: "credentials",
    users: [{
        username: "admin",
        password: "PASTE-THE-HASH-HERE",
        permissions: "*"
    }]
},

Restart Node-RED. Two settings in the same file shrink what is left:

  • uiHost: "127.0.0.1" makes the editor listen only on the machine itself. The default is 0.0.0.0, every IPv4 interface, on port 1880.
  • httpNodeAuth puts a username and password in front of routes created by http in nodes. That matters here because one of the payloads VulnCheck saw was an http in webshell.

Do not give the anonymous user write access. adminAuth accepts a default user, and a default of permissions: "*" puts you back where you started.

Check whether your editor asks for a login

Node-RED's admin API tells you which login scheme is active. From a machine that is not the Node-RED host, run this with your instance's address in place of 192.0.2.10:

curl --max-time 10 http://192.0.2.10:1880/auth/login

A response of {} means no authentication is configured, and anyone who can reach that port can deploy flows. A response containing "type":"credentials" or "type":"strategy" means adminAuth is on. A timeout or refused connection means nothing answered on that address, which is the result you want from outside your network. Run it from outside first, then from the office or plant network, because "only on the internal network" is still an open editor for anything already inside.

What the attack looks like

VulnCheck published the full request. It is a single POST /flows from curl/8.5.0 with three nodes: an empty tab, an inject node set to fire once after one second, and an exec node wired to it. The exec command pipes a base64 string into sh. Decoded, it fetches bot-linux-amd64 from 85.215.73[.]250 port 8080 with wget or curl, saves it as /dev/shm/.b, and starts it with setsid or nohup. The decoy answered the way a real instance would, with HTTP 200 and a new flow revision hash.

There is a side effect the write-ups skip. POST /flows sets the whole active flow configuration, and without the Node-RED-Deployment-Type header Node-RED does a full deploy, stopping every existing node first. The published request carried no rev, which the API treats as a forced deploy. If that body lands on a gateway doing real work, its flows are replaced by the attacker's three nodes. On a production line, "the Node-RED dashboard is suddenly empty" is an indicator.

By November 1, VulnCheck had logged 16 events against this CVE from the same source, 4.201.105[.]116 in Microsoft's AS8075, using at least five user agents. Later payloads fetched a staged script to /tmp/.s, pulled a file from 45.194.90[.]57 port 38472 and saved it as /tmp/.kworker, or skipped downloads and planted a webshell: an http in endpoint such as /cmd wired through a function node into an exec node with the payload appended. The same address hit seven other CVEs, including Apache Solr, Gitea, MLflow and Traefik, which VulnCheck reads as opportunistic mass scanning. VulnCheck did not retrieve the bot or the scripts and makes no claim about what they do.

Review a running instance

If the login check returned {}, assume the flows may have been touched. On the host, list every exec and http in node in the flows file:

jq -r '.[] | select(.type=="exec" or .type=="http in") | [.type, .id, (.command // .url)] | @tsv' ~/.node-red/flows.json

Older installs name the file flows_<hostname>.json. Point jq at that one instead, not at the _cred file next to it.

Anything you did not build is a finding, especially an http in route that feeds a function or exec node. Then look for the drop paths VulnCheck reported:

ls -la /dev/shm/.b /tmp/.s /tmp/.kworker

/dev/shm is memory-backed, so .b disappears on reboot unless the bot set up its own persistence. The webshell variant lives in the flow and survives a restart. If you find either, treat the host as compromised: isolate it, rebuild it, and rotate every credential stored in Node-RED nodes (MQTT brokers, databases, cloud API keys). An exec node runs with the Node-RED process's permissions, and Siemens says on the IoT2050 that means maximum privileges.

Removing the exec node is not the fix

Node-RED's registry honours a nodesExcludes list in settings.js, and nodesExcludes: ["90-exec.js"] stops the core exec node from loading. That breaks the exact flow VulnCheck captured. It does not close the door. Without adminAuth, the same unauthenticated admin API also exposes POST /nodes, which installs palette modules and accepts tarball uploads unless externalModules.palette.allowInstall is false. The shipped settings.js also sets functionExternalModules: true, so function nodes can pull in extra npm modules. Excluding exec and turning those off is defence in depth on top of adminAuth, never a substitute for it.

Who is not in scope

  • SIMATIC IoT2050 Advanced devices without Node-RED installed. Siemens scopes the advisory to devices "running Industrial OS with Node-RED installed".
  • Node-RED instances with adminAuth configured and no write-capable default user. The admin routes require flows.write, so the deploy request gets a 401.
  • Instances whose editor listens only on 127.0.0.1. A local process can still reach it, but a scanner on the network cannot.
  • Other IoT2050 models are not in the Siemens table. If one of them runs Node-RED without adminAuth, the editor is open for the same reason, advisory or not.

What this is not

This is not a code bug in Node-RED, and no node-red npm release fixes it. It is the documented default configuration, reachable from the network, with a CVE attached because a vendor shipped it that way. It is also not on CISA's Known Exploited Vulnerabilities list as of the catalog dated October 30, 2026. VulnCheck added it to its own KEV after the October 30 hit.

The pattern carries over to developer machines. Node-RED turns one HTTP request into a shell command, and so does any local agent tool or MCP server that runs commands without asking. HOL Guard does not protect Node-RED. It puts a review step in front of AI coding agents before they run commands, which is the same lesson applied to a different tool. The HOL Guard CVE-2026-58115 evidence pack holds the source record; this post is the operator write-up.

What do people ask about CVE-2026-58115?

Is CVE-2026-58115 being exploited?

Yes. VulnCheck recorded a successful exploit on a canary on October 30, 2026 and 16 events from the same IP through November 1. It is in VulnCheck KEV but not in CISA KEV as of the October 30, 2026 catalog.

Which version fixes it on the Siemens IoT2050?

Industrial OS V4.3.4.1 or later for SIMATIC IoT2050 Advanced 6ES7647-0BA00-1YA2. Siemens also lists uninstalling or hardening Node-RED as mitigations.

Am I affected if I don't use Siemens hardware?

If your Node-RED editor is reachable over the network without adminAuth, the same request works. Run curl against /auth/login on port 1880. An empty {} response means no login is configured.

Does updating Node-RED fix it?

No. Node-RED ships with the editor unsecured by default. You fix it by setting adminAuth in settings.js and restarting, then limiting who can reach port 1880.

How do I know if my instance was hit?

Look for exec or http in nodes you did not create, an empty or replaced flow set, and the files /dev/shm/.b, /tmp/.s or /tmp/.kworker. Treat any match as a compromise and rebuild the host.

References

All articles

Keep exploring

The engineering desk continues across the ecosystem: security research on shipping agents safely, and plugins that put the standards to work.