I ran npm install on a Raspberry Pi 4, the same one I’d set up as an edge gateway with OPC UA and MQTT, and watched the terminal scroll.
Node-RED, plus three protocol modules for Siemens S7 PLCs, OPC UA, and Modbus. When it finished, I counted.
1,435 packages.
[email protected]
├─┬ [email protected]
│ ├─┬ @openp4nr/[email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── @serialport/[email protected]
│ │ ├─┬ @serialport/[email protected]
│ │ │ ├── @serialport/[email protected]
│ │ │ ├── @serialport/[email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── @serialport/[email protected]
│ │ ├── @serialport/[email protected]
│ │ ├── @serialport/[email protected]
│ │ ...Four npm install commands turned a bare Raspberry Pi into a device carrying 1,435 transitive dependencies. Each one maintained by someone I’ve never met, governed by processes I’ve never reviewed, with security practices I’ve never audited.
That number was in my head two weeks later when the Axios news broke. And it changed how I think about what OT edge platforms actually are.
What Happened #
On March 31, 2026, a North Korean state actor published two malicious versions of Axios, a JavaScript HTTP client downloaded over 100 million times per week. Microsoft attributed the attack to Sapphire Sleet. The attacker compromised a maintainer’s npm access token, changed the registered email to a Proton Mail address, and published two backdoored versions within a 39-minute window.
The payload was a hidden dependency called [email protected], a typosquat of the legitimate crypto-js. It used a postinstall hook to deploy a cross-platform remote access trojan: PowerShell on Windows, a native binary masquerading as an Apple component on macOS, a Python loader on Linux.
flowchart TB
A[Attacker compromises
maintainer npm token]
B[Publishes malicious
axios v1.14.1 and v0.30.4]
C[Hidden dependency
[email protected]]
D[postinstall hook
executes setup.js]
E[Platform-specific RAT
deployed]
F[C2 beacons every 60s
to attacker infrastructure]
A --> B --> C --> D --> E --> F
The malicious packages were live for approximately three hours before being removed.
This was not the first time. left-pad broke build pipelines at Meta and Netflix in 2016. event-stream went undetected for 2.5 months in 2018. The colors.js maintainer deliberately sabotaged his own package (3.3 billion lifetime downloads) in 2022. The XZ Utils backdoor was planted over two years of social engineering and caught by accident when an engineer noticed SSH was running 500 milliseconds slower.
But all of these happened in the IT world. Build pipelines broke, developer machines were compromised, cryptocurrency was stolen. Disruptive, expensive, but ultimately recoverable.
The question I kept coming back to was different: what happens when the same dependency tree runs on a device inside an OT network?
Why This Is Different #
To understand why the Axios attack matters for OT, you first have to understand how much the OT software model has changed.
OT systems used to have zero third-party software dependencies. PLCs ran proprietary firmware. SCADA servers ran vendor-controlled stacks. The software supply chain was one vendor, one codebase, one responsible party.
That model is over. Every major OT vendor (Siemens, Honeywell, Emerson, Schneider Electric, Beckhoff) now offers an edge computing platform built on Linux, Docker, and open-source app ecosystems. The applications are written in Python, Node.js, or Go, packaged as containers, and deployed through vendor app stores or direct installation. This is a genuine step forward. Open platforms reduce vendor lock-in and let operators build solutions tailored to their specific processes.
But they also inherit something proprietary firmware never had: a transitive dependency tree.
The biggest problem in software supply chain security isn’t going from one hundred dependencies to one hundred and one. It’s going from zero to one. And OT just went from zero to 1,435.
I broke down my RPi installation to see where they came from:
| Setup | Packages |
|---|---|
| Empty npm project | 3 |
| Node-RED only | 469 |
| + node-red-contrib-s7 (Siemens S7 PLCs) | 5 |
| + node-red-contrib-modbus | 73 |
| + node-red-contrib-opcua | 920 |
| Node-RED + all three OT modules | 1,435 |
The S7 module is impressively lean at 5 packages. The OPC UA module pulls in 920, reflecting the protocol’s complexity: certificates, address space management, session lifecycle, encryption. Node-RED itself accounts for 469.
This is where it gets interesting. The issue isn’t just the number of dependencies. It’s who ends up running them.
The Path to the Plant Floor #
I checked whether any of these packages actually use Axios. The core protocol libraries (node-opcua, @st-one-io/nodes7, modbus-serial) don’t depend on it. But the platforms built on top of them do.
Node-RED has become the de facto integration layer for industrial edge computing. Siemens ships it as an official app on Industrial Edge. KUNBUS pre-installs it on the Revolution Pi, a Raspberry Pi-based DIN-rail PLC. It runs on Pilz industrial PCs and countless custom edge gateways.
FlowFuse, the enterprise platform for managing Node-RED at scale, ships @flowfuse/node-red-dashboard with 20,000+ weekly downloads. That dashboard lists axios: ^1.13.2 as a direct dependency.
The caret (^) is the detail that matters here. It’s a version range operator that tells npm to automatically accept newer versions it considers compatible (anything up to <2.0.0). When the backdoored [email protected] was published on March 31, any FlowFuse dashboard that ran npm install during the three-hour window would have pulled in the RAT automatically. No user action beyond a routine dependency install.
To be clear: there are no public reports of an OT environment being compromised through this specific path. But the path exists. The dependency is real, the version range is permissive, and the attack was live for three hours. This isn’t a theoretical risk. It’s an unexercised one.
flowchart TB
IE[Siemens Industrial Edge
KUNBUS Revolution Pi
Custom Edge Gateways]
NR[Node-RED
469 packages]
FF[FlowFuse Dashboard
depends on axios]
AX[axios 1.14.1
Backdoored version]
RAT[Cross-platform RAT
deployed on edge device]
IE -->|runs| NR
FF -->|depends on| AX
NR -.->|often paired with| FF
AX --> RAT
style IE fill:#2d9c8f,color:#fff
style NR fill:#2d9c8f,color:#fff
style FF fill:#e67e22,color:#fff
style AX fill:#c0392b,color:#fff
style RAT fill:#c0392b,color:#fff
The attack surface isn’t in the protocol library talking to your PLC. It’s in the dashboard, the management layer, the tooling that wraps around it. These are the parts that get adopted without anyone auditing the full dependency tree.
And this isn’t just about supply chain attacks. Node-RED itself had a CVSS 10.0 vulnerability in 2025 (CVE-2025-41656) because it didn’t enforce authentication by default. Any Revolution Pi on the network was open to unauthenticated remote code execution via injected flows. Node-RED only made authentication mandatory in version 4.0.
Different class of vulnerability. Same underlying problem: IT tools adopted in OT environments carry IT risks that OT teams aren’t used to managing.
What Makes OT Worse #
In IT, the Axios attack was a three-hour exposure window. Detect, patch, redeploy.
OT doesn’t work like that. I’ve deployed unidirectional gateways at facilities with 15-year-old equipment. I’ve worked with SCADA systems where a patching window requires planned downtime, safety reviews, regression testing, and change management approval. That process can take months. A dependency update that introduces unexpected behaviour isn’t an inconvenience. It’s a production risk. Siemens estimates unplanned downtime in industrial operations costs $100,000+ per hour on average.
According to Synopsys’ 2025 Open Source Security and Risk Analysis (OSSRA) report, 92% of audited codebases contain components that are 4 or more years out-of-date. In IT, that’s a compliance finding. In OT, that’s the norm.
Then there’s the air gap question. Industrial edge platforms connect to app stores, pull container images, download updates, and sync with cloud management consoles. As Dragos noted in their 2026 OT Cybersecurity report:
“We have never found an organization that is truly air gapped.”
And the consequences are different in kind, not just degree. A crashing npm package in a web application means a user sees an error page. A crashing npm package on an edge device controlling a process means a physical system behaves unexpectedly. OT governs turbines, valves, conveyor belts, chemical reactors. The consequences aren’t measured in page load times. They’re measured in equipment damage, environmental releases, and human safety.
What This Means in Practice #
The answer isn’t to reject edge platforms. The benefits are real. The answer is to adopt them with the same rigour that OT applies to every other engineering decision.
Start with visibility. A Software Bill of Materials (SBOM) is a formal inventory of every component in your software. IEC 62443-4-1 requires vendors to maintain an inventory of third-party components (SM-9) and a process to manage their security risks (SM-10). I generated an SBOM from my RPi installation using Syft, and it catalogued 545 unique packages and 22 executables. Scanning that SBOM with Grype found zero known vulnerabilities today.
But here’s the thing: a clean scan doesn’t protect against a supply chain attack that hasn’t happened yet. Scanning is reactive. You need preventive measures too.
Pin your dependencies. Specifying exact versions ("axios": "1.7.7", not "axios": "^1.7.7") is how you prevent automatic resolution to a compromised version. The caret is exactly how the malicious Axios versions reached downstream consumers. Use lock files and install with npm ci for reproducible builds. Consider the --min-release-age flag to block brand-new package versions. This alone would have prevented the Axios attack, where the malicious version was live for only three hours.
Scan every container before it touches the OT network. Tools like Trivy and Grype can be integrated into CI/CD pipelines to catch known vulnerabilities before deployment.
And question every dependency. Before adding a package, ask: can I write this in 10 lines? left-pad was an 11-line function. Fewer dependencies mean a smaller attack surface, fewer things to patch, and fewer opportunities for compromise.
The Bigger Picture #
The sophistication of supply chain attacks is increasing. The Axios attack was detected in three hours. The event-stream attack took two and a half months. The XZ Utils backdoor took two years.
According to Sonatype’s 2025 State of the Software Supply Chain report, 454,648 malicious packages were discovered across open-source registries that year, and over 99% of all open-source malware targeted npm.
The biggest risk isn’t any single vulnerability. It’s the assumption that OT can adopt IT’s tools without inheriting IT’s problems. Edge platforms bring real value to industrial operations. But every npm install on an OT-connected device is a decision that deserves the same scrutiny as selecting a safety-rated component for a control panel.
My Raspberry Pi is clean today. But it’s carrying 1,435 reasons to stay vigilant.