Supply Chain Attacks in Robotic Software
/ 5 min read
Table of Contents
In industrial robotics, we worry a lot about safety: collision detection, emergency stops, sensor failures. But there’s another risk that doesn’t get enough attention: supply chain attacks. Your robot control software probably depends on dozens of third-party libraries, and any one of them could become attack vector.
What Supply Chain Attack Actually Means
Supply chain attack happens when malicious code gets injected into software through trusted dependencies. You’re not the target - the library you depend on is. Attackers compromise popular package, your build system pulls it automatically, and suddenly malicious code runs in your production systems.
In robotics context, this is particularly dangerous. We’re talking about physical systems that can cause real damage. Compromised navigation library could make robot ignore safety zones. Corrupted sensor fusion code could misreport positions. These aren’t just data breaches - they’re safety incidents.
Real Risks in Industrial Robotics
Here are some real concerns in industrial automation systems:
Dependency hell: Modern robotics software stack is massive. Our system uses OpenCV for vision, Eigen for math, Boost for utilities, Qt for UI, plus dozens of smaller libraries. Each one is potential entry point.
Automatic updates: CI/CD pipelines often pull latest versions automatically. Great for getting security patches, but also means compromised package update gets deployed immediately.
Limited visibility: Most teams don’t actually audit their dependencies. You know you’re using OpenCV, but do you know all 47 transitive dependencies it brings along? Probably not.
Long deployment cycles: Industrial systems often run for years without updates. Once compromised code gets deployed, it might stay there long time before anyone notices.
What We Actually Do
In my current work on robotics platforms, we’ve implemented several practical measures:
Pin Dependency Versions
Never use “latest” or floating versions in production. Lock everything:
# Bad - pulls whatever is newestfind_package(Boost REQUIRED)
# Good - explicit version pinningfind_package(Boost 1.80.0 EXACT REQUIRED)Yes, you miss automatic security updates. But you also prevent automatic compromises. We update dependencies deliberately, not automatically.
Use Private Package Mirrors
Don’t pull directly from public repositories in production builds. We maintain internal mirror:
# vcpkg configuration pointing to internal mirrorset(VCPKG_BINARY_SOURCES "clear;nuget,https://internal-mirror.company.com/vcpkg,readwrite")When public package gets compromised, our production systems keep building with last known good version. We have time to investigate before updating.
Hash Verification
Always verify package hashes:
include(FetchContent)
FetchContent_Declare( spdlog URL https://github.com/gabime/spdlog/archive/refs/tags/v1.12.0.tar.gz URL_HASH SHA256=4dccf2d10f410c1e2feaff89966c49b6e311f5e9e5b4448a7a2f9c5f4db18f6a)If hash doesn’t match, build fails. Simple protection that catches tampering.
Regular Dependency Audits
We audit dependencies. Not fun work, but necessary:
- List all direct dependencies
- Generate dependency tree with transitive deps
- Check each package for known vulnerabilities
- Review what each dependency actually does
- Remove unused dependencies
Found out we were pulling entire library just to use one header file. Replaced with our own 50-line implementation.
Vendor Critical Dependencies
For absolutely critical libraries, we vendor them - copy source code into our repository:
third_party/ ├── eigen/ # Vendored, we control updates ├── json/ # Vendored └── protobuf/ # VendoredMore maintenance work, but complete control over when and how these update. For safety-critical components, worth the effort.
Isolated Build Environment
Our Jenkins builds run in Docker containers with no network access after dependency download:
FROM ubuntu:22.04
# Install dependencies firstRUN apt-get update && apt-get install -y build-essential cmake
# Copy dependency cacheCOPY --from=dependency-cache /vcpkg /vcpkg
# Network gets disabled here# Build happens with only cached dependenciesEven if package repository gets compromised during build, we’re using cached versions.
What About Open Source?
People ask: “Isn’t open source more vulnerable?” Actually it’s opposite. With closed-source vendor libraries, you have no idea what’s in them. At least with open source, you can audit code if needed.
We prefer established open source libraries over random proprietary SDKs. Boost and Eigen have thousands of eyes reviewing them. That random “RobotUtils.dll” from small vendor? Who knows what’s inside.
The Balance
Here’s the thing - you can’t eliminate all risk. Pinning versions means you miss security patches. Vendoring everything creates maintenance burden. Using no dependencies means reinventing wheels poorly.
The goal is not perfect security. It’s reducing risk to acceptable level while still shipping products. We focus on:
- Critical path dependencies: Libraries that touch hardware control, safety systems, or network communication get extra scrutiny
- Minimal dependencies: Every dependency is liability. Only add what you actually need
- Defense in depth: Multiple layers - hash verification, pinned versions, private mirrors, regular audits
Practical Checklist
Before adding new dependency to robotics project:
- Is this dependency actually necessary, or can we implement ourselves?
- Is it actively maintained? When was last commit?
- How many transitive dependencies does it bring?
- Can we vendor it for critical components?
- Do we have hash verification in place?
- Are versions pinned, not floating?
The Reality
Supply chain attacks are not theoretical concern. We’ve seen npm packages with millions of downloads get compromised. Python packages with backdoors. Even hardware supply chains get targeted.
In robotics, stakes are higher than typical web application. Compromised code doesn’t just leak data - it controls physical systems that can hurt people. Taking supply chain security seriously isn’t paranoia, it’s responsible engineering.
Start with basics: pin your versions, verify hashes, audit regularly. You don’t need perfect solution, just good enough defense to make your system harder target than the next one.