Paper Summary: The cFS Attack Surface, from the Bottom Up
This post summarizes my 2024 IEEE SMC-IT paper "Attack Surface Analysis for Spacecraft Flight Software" co-authored with Gregory Falco.
There's a principle from formal verification of financial algorithms that stuck with me: you cannot properly reason about the behavior of a system higher in the stack unless you have verified the properties of the subsystems executing its intentions. Passmore and Ignatovich wrote that about trading systems, but it applies directly to flight software. The RTOS is the foundation everything else depends on. If an attacker can manipulate it, nothing above it can be trusted--and the layers above may not even detect that anything has changed.
Rather than starting at the application layer where most security discussions happen, we went to the bottom of the stack and worked up.
The Stack Nobody Examines
We chose NASA's core Flight System (cFS) running on the RTEMS real-time operating system because both are open source, widely used in actual missions, and architecturally representative of how most flight software is built. The cFS architecture is a layered stack: hardware and BSP at the bottom, then RTEMS, then the Operating System Abstraction Layer (OSAL), then the cFS platform services, and finally the mission applications on top. We deliberately focused our analysis on the lower layers--the RTOS and OSAL--because they had received almost no security scrutiny despite being the layers everything else rests on.
What we found was revealing, not because of exotic vulnerabilities, but because of how many attack-relevant properties are simply inherent to the architecture.
Everything Runs in One Address Space
RTEMS is a single-process RTOS. All code--the operating system, the abstraction layer, every application--shares one address space and is statically linked into a single binary image. There is no memory protection between tasks. If an attacker gains code execution in any component, they have unrestricted access to all memory and can influence every other task on the system.
This isn't a bug. It's the design. RTEMS prioritizes simplicity and deterministic real-time performance, and memory protection adds overhead and complexity that conflicts with those goals. But from a security perspective, it means there's no containment. A compromise anywhere is a compromise everywhere. FreeRTOS vulnerabilities that led to remote code execution and data leakage show this isn't theoretical--RTOSes do get attacked, and when they lack isolation, a single vulnerability compromises the entire system.
The Abstraction Layer Paradox
The OSAL exists for good reasons. It lets cFS run on RTEMS, vxWorks, Linux, or FreeRTOS without changing application code. Developers can prototype on Linux and deploy on RTEMS. That flexibility is valuable.
But abstraction layers add code, and more code means more potential for vulnerabilities. The OSAL wraps each target OS's functionality in C, and the wrapper implementations sometimes include additional logic to bridge gaps between what the OSAL API promises and what the underlying OS actually provides. Those gaps are where bugs hide. The abstraction also obscures interactions with the underlying system, making it harder to tune security controls or detect malicious activity at the application layer. You're trading visibility for portability, and in a security context, visibility matters.
Living Off the Land, in Orbit
One finding that stands out: RTEMS includes a full shell, analogous to a Unix shell, with commands for file system manipulation, memory dumping and editing, system information queries, and managing the dynamic loader. The OSAL's BSP configuration activates this shell with all commands enabled. During development and testing, this is useful. On an operational spacecraft, it's an attacker's toolkit already installed and waiting.
An adversary who gains access doesn't need to upload tools--the shell provides substantial "living off the land" capabilities. Combined with the lack of memory protection, an attacker could use the shell to inspect memory, modify running code, or load new executable modules through the dynamic loader. RTEMS does implement user and group access controls for shell commands, but given that the RTOS has no memory protection between tasks, those controls can be circumvented by any code running in the same address space.
The BSP configuration also enables four file systems by default (ImFS, DOS/FAT, DevFS, and RFS) without disabling any ImFS functionalities. Each enabled file system is code sitting in memory, and vulnerabilities in unused file system drivers become attack surface that serves no operational purpose.
The Path Forward
The recommendations follow directly from the findings: simplify. Disable the shell, the dynamic loader, and unused file systems in flight configurations. Evaluate whether the OSAL's abstraction is worth its security cost for missions committed to a single RTOS. Consider memory-safe languages for new development. Apply formal verification to the RTOS layer, because until we can verify the foundation's behavior, we're building on assumptions.
None of this is easy, and the paper doesn't pretend it is. These are architectural properties baked into systems with decades of flight heritage. But understanding the attack surface is the prerequisite for reducing it, and that understanding has to start at the bottom of the stack.