The forgotten sibling: unauthenticated RCE in Yamcs mission control
I recently reported a security advisory in Yamcs, the open-source mission control system used to operate satellites, payloads, and ground stations. It is fixed in 5.13.6, advisory GHSA-wqq5-5w4p-m569.
| Advisory | GHSA-wqq5-5w4p-m569 |
| Affected | org.yamcs:yamcs-core ≤ 5.13.5 |
| Fixed | 5.13.6 |
| Impact | RCE as the Yamcs service account — unauthenticated in the default config |
A twin left behind
Yamcs had already patched a YAML template injection,
CVE-2026-55559, by routing the
instance create path through a safe renderer
(template.processAndSanitizeYaml()). Its twin, the reconfigure path, was left
on the old unsafe one — template.process() at YamcsServer.java:693.
Same bug, same sink, one fixed and its sibling forgotten.
The bug
A template argument is rendered inside a quoted scalar, e.g. name: "{{ spaceSystem }}".
Because the reconfigure path never sanitizes the rendered YAML, a crafted argument can
close the quote and inject a top-level services: key. SnakeYAML keeps the last
duplicate key, so the injected service wins — and org.yamcs.ProcessRunner runs a shell
command when the instance restarts.
POST /api/instances/{instance}:reconfigure
Content-Type: application/json
{"templateArgs":{"spaceSystem":"x\"\nservices:\n - class: org.yamcs.ProcessRunner\n args:\n command: [\"sh\",\"-c\",\"id\"]\n#"}}
In its default configuration (no security.yaml), one crafted, unauthenticated
reconfigure request injects a service that runs a shell command on spacecraft mission
control. The instance auto-restarts and executes it:

Sources: PoC & full write-up on GitHub · originally posted on LinkedIn.
Takeaway
The takeaway is simple. A patched line is a map, not the destination. When a bug is fixed, check its sibling — the one that does the same thing through the same dangerous call.
Coordinated disclosure. Reported privately on 2026-08-29, fixed in 5.13.6 on 2026-10-01. Don't run this against systems you don't own.