← go home回首頁
EN 繁中

Node-RED's CVSS 10: One HTTP Request Gets You a Shell, and No Login Is the Default

You've probably heard of Node-RED — that browser-based tool where you drag and drop nodes to wire up devices, APIs, and services. Home Assistant folks on a Raspberry Pi, factory engineers connecting sensors, homelab tinkerers running automations — everyone uses it.

On August 11, 2026, Siemens published an advisory for the Node-RED bundled with their SIMATIC IoT2050 Advanced: CVE-2026-58115, CVSS 10.0. The issue is not subtle: Node-RED's HTTP interface has no login by default, and Node-RED's exec node can run shell commands. (source: Siemens SSA-834709)

On October 30, VulnCheck's canary network caught in-the-wild exploitation: a single POST /flows deploys a flow with an exec node, base64-decodes a command, pipes it to /bin/sh, wgets a bot to /dev/shm/.b, and launches it detached with setsid. Done. (source: VulnCheck)

Plain-English Intro

Imagine there's a printer in your office that anyone who walks by can press "print" on, and next to the printer is a box full of company-confidential documents. Node-RED's default is like that: the editor and the admin API are open to the network with no password field. And "deploying a flow" is technically the same as "running code on this machine" — because Node-RED has exec nodes and function nodes that call the operating system directly.

💡 Key takeaway: This isn't a code bug in Node-RED. It's a default configuration. The official docs say it plainly: "By default, the Node-RED editor is not secured." (source: Node-RED Security Guide) No version upgrade fixes it for you — you have to enable adminAuth yourself.

Node-RED CVE-2026-58115 attack chain: one POST /flows from scan to /bin/sh, with observed payload variants and fix path

What the vulnerability actually is

CVE-2026-58115 was assigned by Siemens for their SIMATIC IoT2050 Advanced (order number 6ES7647-0BA00-1YA2), affecting "all versions before V4.3.4.1 running Industrial OS with Node-RED installed." CWE-306: Missing authentication for a critical function. (source: NVD)

But the root cause isn't Siemens' — it's Node-RED's default. Siemens' advisory is direct: "do not enforce authentication on the Node-RED HTTP interface, allowing unauthenticated access to programming nodes that are capable of executing system commands." CVSS 3.1 and 4.0 both score 10.0, vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — network vector, low complexity, no privileges, no user interaction, scope changed. (source: Siemens CSAF)

CISA republished the advisory as ICS advisory ICSA-26-237-03 on August 25, listing affected critical-infrastructure sectors: Chemical, Critical Manufacturing, Energy, and Transportation Systems. (source: CISA ICSA-26-237-03)

⚠️ This isn't only a Siemens problem: Any Node-RED instance without adminAuth is in scope — a Raspberry Pi, a Docker container, a factory server. VulnCheck's conclusion: "Node-RED instances without adminAuth are being found and exploited automatically." In July 2025, the Pilz IndustrialPI 4 had the same class of issue (CVE-2025-41656, also CVSS 10). (source: Ciphers Security, CERT@VDE VDE-2025-045)

The attack chain: one request, one-second delay

Between October 30 and November 1, VulnCheck captured 16 events from a single IP (4.201.105[.]116, AS8075, Microsoft's network, geolocated to Brazil). The flow:

  1. Recon — Scan port 1880, GET /auth/login returns {} (empty JSON = no auth)
  2. Deploy — Single POST /flows with a flow containing: inject (fires once, 1 second after deploy) → exec (runs a shell command)
  3. Execute — The exec node decodes a base64 string and pipes it to /bin/sh
  4. Download — wget from 85.215.73[.]250:8080 pulls bot-linux-amd64, saves it as /dev/shm/.b
  5. Launch — chmod +x, then setsid (or nohup fallback) for detached execution

The same IP hit 125 times across 8 different CVEs (including a 2019 Apache Solr bug, CVE-2019-17558). VulnCheck calls it "opportunistic mass scanning" rather than a targeted campaign. The bot's capabilities are unpublished — VulnCheck didn't retrieve the binary and has no hashes. (source: VulnCheck, SecurityWeek)

By November 1, variants appeared: a staged script to /tmp/.s, a .sys_update file saved as /tmp/.kworker (mimicking a kernel worker thread name), and webshells — an HTTP In endpoint (e.g., /cmd) wired to an exec node, letting the attacker send commands via URL parameters later. The webshell is worse than the RAM-resident bot: it lives in your flows and survives a reboot.

Check if you're affected

Run these on your machine:


# 1. Does the admin API require login?
curl -s -m 5 http://localhost:1880/auth/login
# {} = no auth (exposed)
# {"type":"credentials","prompts":[...]} = protected

# 2. Is adminAuth actually set in settings.js?
grep -nE '^[[:space:]]*(adminAuth|httpNodeAuth|uiHost|uiPort|httpAdminRoot)[[:space:]]*:' ~/.node-red/settings.js
# No output = no editor login configured

# 3. What's it listening on?
sudo ss -ltnp | grep ':1880'
# 0.0.0.0:1880 = all interfaces; 127.0.0.1:1880 = local only

# 4. Reachable from the internet? (test from phone hotspot or another machine)
nc -vz -w 5 <your-public-ip> 1880
curl -s -m 5 http://<your-public-ip>:1880/auth/login

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

# 6. Check the drop paths VulnCheck published
ls -la /dev/shm/.b /tmp/.s /tmp/.kworker 2>/dev/null
ps -eo pid,ppid,user,lstart,args | grep -E '/dev/shm/.b|/tmp/.kworker' | grep -v grep

The fix: three steps

1. Enable adminAuth (on every Node-RED you run)


# Generate the bcrypt hash
node-red admin hash-pw
# Put the hash in settings.js:

// settings.js
adminAuth: {
    type: "credentials",
    users: [{
        username: "admin",
        password: "<bcrypt hash>",
        permissions: "*"
    }]
},
httpNodeAuth: { user: "flowuser", pass: "<bcrypt hash>" },

httpNodeAuth protects the routes your HTTP In nodes publish — the flows' public endpoints also need auth. (source: Node-RED Security Guide)

2. Bind to localhost or a management network


// settings.js
uiHost: "127.0.0.1",

Docker: -p 127.0.0.1:1880:1880, not -p 1880:1880. Engineers reach the editor via SSH tunnel or VPN.

3. Siemens IoT2050 users: update to V4.3.4.1

Siemens lists three options: update, uninstall Node-RED, or harden it per the Node-RED docs. If you can't update yet, at minimum confirm port 1880 isn't exposed.

⚠️ If you find an unfamiliar flow, treat the host as compromised: The /dev/shm payload vanishes on reboot, but webshell flows don't. Capture evidence before rebooting. Start Node-RED with --safe to load the editor without running flows — that lets you review and remove unknown exec, HTTP In, and function nodes. (source: Ciphers Security)

How this fits the pattern

If you've been reading this blog's security posts, you've seen this shape before:

DateTopicShared root cause
11/1LMDeploy SSRF (CVE-2026-33626)Inference server, no auth → pivot from inside
11/3Langflow 33 CVEsAgent builder, default auto-login → unauthenticated RCE
11/4Node-RED (CVE-2026-58115)IoT/OT tool, no auth by default → one request = shell

Three different domains (inference, agent building, IoT), same root: the default doesn't require credentials, and the tool can execute code. Self-hosted tools all assume "only you can reach it" — but a port forward, a DMZ rule, or a NAT traversal can turn "only you" into "anyone."

If You're Stuck

  • /auth/login returns {} but you're not sure it means "no auth" → Also open http://host:1880/ in a browser. If the editor loads without a login form, it's open.
  • Changed settings.js but nothing happened → Confirm you edited the file Node-RED actually reads. The startup log prints the path as Settings file :.
  • Docker: editing settings.js on the host has no effect → You need to volume-mount the modified settings into the container, not just edit the file on the host.
  • Can't log in after enabling adminAuth → The password is a bcrypt hash, not plaintext. Run node-red admin hash-pw to generate one.
  • Updated Siemens firmware but still exposed → V4.3.4.1 fixes the specific advisory. If you installed Node-RED separately (not the one bundled with the IoT2050), the firmware update won't enable adminAuth for you.
  • Can't find settings.js → The startup log prints the path. Default is ~/.node-red/settings.js.
  • disableEditor: true — is that enough? → No. It hides the UI but the admin API stays active. Use httpAdminRoot: false to disable all admin endpoints.

Further Reading

Sources