Skip to content

CVE-2026-57527: Verified Repro With Script Download

CVE-2026-57527: ZAP ViewState add-on insecure deserialization RCE

CVE-2026-57527 is verified against zaproxy/zap-extensions · github. Affected versions: ViewState add-on versions 1, 2, and 3 (before version 4). Fixed in ViewState add-on version 4. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00249.

REPRO-2026-00249 zaproxy/zap-extensions · github RCE Variant found Jul 6, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.8
Confidence
HIGH
Reproduced in
26m 16s
Tool calls
263
Spend
$7.43
01 · Overview

What Is CVE-2026-57527?

CVE-2026-57527 is a high-severity insecure deserialization vulnerability in the Zed Attack Proxy (ZAP) ViewState add-on (versions 1-3, before version 4), where a malicious proxied web server can trigger arbitrary code execution inside the ZAP process. Pruva reproduced it (reproduction REPRO-2026-00249).

02 · Severity & CVSS

CVE-2026-57527 Severity & CVSS Score

CVE-2026-57527 is rated high severity, with a CVSS base score of 8.8 out of 10.

HIGH threat level
8.8 / 10 CVSS base
Weakness CWE-502 — Deserialization of Untrusted Data

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected zaproxy/zap-extensions Versions

zaproxy/zap-extensions · github versions ViewState add-on versions 1, 2, and 3 (before version 4) are affected.

How to Reproduce CVE-2026-57527

$ pruva-verify REPRO-2026-00249
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00249/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-57527

Remote code execution — reproduced
  • 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
Trigger

Base64 Java serialized object in javax.faces.ViewState field served by malicious TCP HTTP peer

Attack chain
  1. TCP HTTP response
  2. ZAP HttpMessage
  3. ViewState response panel
  4. ViewStateModel
  5. JSFViewState.decode
  6. ObjectInputStream.readObject
Runnable proof: reproduction_steps.sh
Captured evidence: fixed harness 1fixed harness 2server fixed 1server fixed 2
Variants tested

A malicious javax.faces.ViewState value in a proxied HTTP request body reaches the same JSFViewState.decode/ObjectInputStream.readObject sink through the ViewState add-on request-panel factory on vulnerable versions. The fixed commit blocks this alternate trigger by removing the shared JSF registration, so no fixed-ve…

How the agent worked 550 events · 263 tool calls · 26 min
26 minDuration
263Tool calls
116Reasoning steps
550Events
3Dead-ends
Agent activity over 26 min
Support
17
Hypothesis
2
Repro
310
Judge
96
Variant
120
0:0026:16

Root Cause and Exploit Chain for CVE-2026-57527

Versions: ViewState add-on versions before version 4 / before fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c. The verified vulnerable checkout is the fixed commit parent 7e686c0900e82bb73b57880c0328d012269f8741.

CVE-2026-57527 affects the ZAP ViewState add-on before the fix in commit ac6c3f94d38505bc0facea286a4d3728044c6e5c. The add-on's response ViewState panel registered the JSF parameter name javax.faces.ViewState; when a proxied HTTP response contained that hidden field, the original ZAP add-on path created a JSFViewState and decoded it with Java ObjectInputStream.readObject() without a deserialization filter or type allowlist. A malicious web server controlling a response viewed/proxied through ZAP can therefore supply a Base64-encoded serialized Java object that is deserialized inside the ZAP JVM. The current reproduction confirms arbitrary command execution through the actual built ZAP ViewState add-on component path, not a reimplemented handler.

  • Package/component affected: zap-extensions, add-on addOns/viewstate / ZAP ViewState add-on.
  • Affected versions: ViewState add-on versions before version 4 / before fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c. The verified vulnerable checkout is the fixed commit parent 7e686c0900e82bb73b57880c0328d012269f8741.
  • Risk level and consequences: High. An attacker-controlled proxied web server can return an HTML response containing a malicious javax.faces.ViewState value. When the vulnerable ZAP ViewState add-on response panel processes that response, attacker-controlled Java deserialization occurs in the ZAP process and can execute commands with the privileges of the ZAP user.

Impact Parity

  • Disclosed/claimed maximum impact: Arbitrary code execution / RCE through ZAP processing a proxied malicious ViewState response.
  • Reproduced impact from this run: Code execution. The payload's readObject() ran /bin/sh -c "id > ...; echo RCE_VIA_ZAP_VIEWSTATE_PRODUCT_PATH >> ..." inside the deserializing JVM, producing marker files and command output.
  • Parity: full.
  • Not demonstrated: A full desktop browser GUI session was not used. Instead, the proof builds the actual vulnerable and fixed .zap add-on archives and drives the original response-panel product component boundary with a real ZAP HttpMessage populated from bytes read across a TCP socket. This reaches the original ZAP add-on path (ExtensionHttpPanelViewStateView$ResponseSplitBodyViewStateViewFactory -> HttpPanelViewStateView -> ViewStateModel -> JSFViewState.decode) and demonstrates the claimed code-execution impact.

Root Cause

The vulnerable ViewStateModel registered JSF ViewState fields as parseable ViewState parameters:

viewstateParams.add(new ViewState(null, JSFViewState.KEY, "javax.faces.ViewState"));

For response bodies, ViewStateModel.getData() calls getViewStateParam() on the HTTP response body. If javax.faces.ViewState is found, getViewStateParam() constructs a JSFViewState object. ViewState.getDecodedValue() then calls JSFViewState.decode(), whose vulnerable implementation Base64-decodes the supplied value and passes it directly to ObjectInputStream.readObject():

ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();

Because the serialized stream is attacker-controlled and no Java serialization filter, class allowlist, or safe parser is used, a gadget or attacker-defined serializable class available to the deserializing JVM can execute code during readObject().

The known fix is commit ac6c3f94d38505bc0facea286a4d3728044c6e5c (https://github.com/zaproxy/zap-extensions/commit/ac6c3f94d38505bc0facea286a4d3728044c6e5c), which disables the JSF ViewState registration in ViewStateModel:

// viewstateParams.add(new ViewState(null, JSFViewState.KEY, "javax.faces.ViewState"));

With that change, the fixed add-on does not create JSFViewState for the same response field and therefore does not reach JSFViewState.decode() for the malicious input.

Reproduction Steps

  1. Use bundle/repro/reproduction_steps.sh.
  2. The script:
    • Locates the prepared zap-extensions repository from bundle/project_cache_context.json or clones a fallback checkout.
    • Resolves the fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c and vulnerable parent 7e686c0900e82bb73b57880c0328d012269f8741.
    • Creates clean worktrees for both versions and verifies the JSF registration is active in the vulnerable checkout and commented out in the fixed checkout.
    • Builds the actual ViewState add-on .zap archive from each checkout with Gradle task :addOns:viewstate:jarZapAddOn.
    • Starts a real malicious TCP HTTP server that serves an HTML page with a hidden javax.faces.ViewState field containing a Base64 serialized Java object.
    • Runs a Java product-component harness that reads the malicious HTTP response from the TCP socket, creates a real ZAP HttpMessage, instantiates the original ExtensionHttpPanelViewStateView$ResponseSplitBodyViewStateViewFactory, obtains the original HttpPanelViewStateView, and triggers the normal HttpPanelViewModel.setMessage(HttpMessage) listener path.
    • Performs two vulnerable attempts and two fixed negative-control attempts.
  3. Expected evidence:
    • Vulnerable attempts log that ViewStateModel and HttpPanelViewStateView were loaded from the vulnerable built .zap, show ViewStateModel.has_jsf_registration=true, and create vuln_marker_1.txt/vuln_marker_2.txt plus vuln_rce_output_1.txt/vuln_rce_output_2.txt.
    • The marker stack traces include JSFViewState.decode, ViewStateModel.getData, HttpPanelViewStateView.dataChanged, and DefaultHttpPanelViewModel.setMessage.
    • Fixed attempts log that classes were loaded from the fixed built .zap, show ViewStateModel.has_jsf_registration=false, and do not create marker/RCE files.

Evidence

Primary evidence files:

  • bundle/repro/reproduction_steps.sh — verified twice consecutively.
  • bundle/repro/runtime_manifest.json — runtime manifest with entrypoint_kind="tcp_peer", service_started=true, healthcheck_passed=true, and target_path_reached=true.
  • bundle/logs/reproduction_steps.log — full build and runtime transcript.
  • bundle/logs/vuln_harness_1.log, bundle/logs/vuln_harness_2.log — vulnerable product-path harness logs.
  • bundle/logs/fixed_harness_1.log, bundle/logs/fixed_harness_2.log — fixed negative-control harness logs.
  • bundle/logs/server_vuln_1.log, bundle/logs/server_vuln_2.log, bundle/logs/server_fixed_1.log, bundle/logs/server_fixed_2.log — malicious TCP server logs proving accepted HTTP connections.
  • bundle/repro/artifacts/vuln_marker_1.txt, bundle/repro/artifacts/vuln_marker_2.txt — deserialization marker files containing stack traces.
  • bundle/repro/artifacts/vuln_rce_output_1.txt, bundle/repro/artifacts/vuln_rce_output_2.txt — command output files.
  • bundle/repro/artifacts/source_identity.txt — vulnerable/fixed commit IDs and SHA-256 hashes of the built .zap archives.
  • bundle/repro/artifacts/fix.patch — patch diff for the ViewState add-on.

Key excerpts from the successful run:

[setup] Vulnerable commit (fixed parent): 7e686c0900e82bb73b57880c0328d012269f8741
[setup] Fixed commit:                    ac6c3f94d38505bc0facea286a4d3728044c6e5c
[verify] Vulnerable ViewStateModel JSF registration:
... ViewStateModel.java:62:        viewstateParams.add(new ViewState(null, JSFViewState.KEY, "javax.faces.ViewState"));
[verify] Fixed ViewStateModel JSF registration is disabled:
... ViewStateModel.java:62:        // viewstateParams.add(new ViewState(null, JSFViewState.KEY, "javax.faces.ViewState"));

The vulnerable runtime path loaded the actual vulnerable add-on and saw the JSF registration:

[vuln-1] view_loaded_from=file:.../worktrees/vulnerable/addOns/viewstate/build/zapAddOn/bin/viewstate-alpha-4.zap
ViewStateModel.loaded_from=file:.../worktrees/vulnerable/addOns/viewstate/build/zapAddOn/bin/viewstate-alpha-4.zap
ViewStateModel.param name=javax.faces.ViewState type=JSF
ViewStateModel.has_jsf_registration=true
[vuln-1] invoking real HttpPanelViewModel.setMessage(HttpMessage)
[vuln-1] marker_exists=true
[vuln-1] rce_output_exists=true

The RCE marker confirms deserialization and shows the original ZAP add-on call stack:

DESERIALIZATION_RCE_CONFIRMED
command=id > '.../vuln_rce_output_1.txt'; echo RCE_VIA_ZAP_VIEWSTATE_PRODUCT_PATH >> '.../vuln_rce_output_1.txt'
...
  at org.zaproxy.zap.extension.viewstate.zap.utils.JSFViewState.decode(JSFViewState.java:92)
  at org.zaproxy.zap.extension.viewstate.zap.utils.JSFViewState.decode(JSFViewState.java:76)
  at org.zaproxy.zap.extension.viewstate.zap.utils.ViewState.getDecodedValue(ViewState.java:64)
  at org.zaproxy.zap.extension.viewstate.ViewStateModel.getData(ViewStateModel.java:183)
  at org.zaproxy.zap.extension.viewstate.HttpPanelViewStateView.dataChanged(HttpPanelViewStateView.java:189)
  at org.zaproxy.zap.extension.httppanel.view.DefaultHttpPanelViewModel.setMessage(DefaultHttpPanelViewModel.java:42)

The command output proves attacker-controlled code ran in the deserializing JVM:

uid=1000(vscode) gid=1000(vscode) groups=1000(vscode),969(969)
RCE_VIA_ZAP_VIEWSTATE_PRODUCT_PATH

The fixed negative controls process the same malicious response through the fixed built add-on but do not deserialize it:

[fixed-1] view_loaded_from=file:.../worktrees/fixed/addOns/viewstate/build/zapAddOn/bin/viewstate-alpha-4.zap
ViewStateModel.param_count=2
ViewStateModel.param name=__VIEWSTATE type=ASP
ViewStateModel.param name=__VIEWSTATEFIELDCOUNT type=ASP
ViewStateModel.has_jsf_registration=false
[fixed-1] marker_exists=false
[fixed-1] rce_output_exists=false

Environment details captured by the script include OpenJDK version, exact commits, built archive paths, SHA-256 hashes, TCP server logs, and runtime manifest metadata.

Recommendations / Next Steps

  • Keep the JSF ViewState parser disabled unless it is replaced with a safe, non-deserializing parser.
  • If JSF ViewState support is restored, do not call unrestricted ObjectInputStream.readObject() on data from HTTP responses. Use a strictly bounded parser or, at minimum, a JEP 290 ObjectInputFilter with a tight allowlist and resource limits.
  • Release and deploy ViewState add-on version 4 or later containing commit ac6c3f94d38505bc0facea286a4d3728044c6e5c.
  • Add regression tests that feed a serialized-object-looking javax.faces.ViewState response through the actual response-panel model path and assert that JSFViewState.decode()/ObjectInputStream.readObject() is not reached.
  • Consider auditing other add-ons for Java deserialization of proxied request/response data.

Additional Notes

  • Idempotency confirmed: bundle/repro/reproduction_steps.sh was run twice consecutively and passed both times.
  • The proof uses a headless product-component boundary rather than launching the full Swing desktop. It still loads the actual built .zap add-on classes and drives the original response-panel listener/model path with a real ZAP HttpMessage created from bytes received across a TCP socket.
  • The harness only initializes minimal Swing/I18N state needed for headless execution; it does not reimplement ViewState selection or toggle the fix. The vulnerable/fixed comparison is produced by building and loading different add-on archives from the vulnerable and fixed commits.
  • No sanitizer was used; the observed impact is real Java command execution during deserialization.

Variant Analysis & Alternative Triggers for CVE-2026-57527

Versions: versions as tested: vulnerable parent 7e686c0900e82bb73b57880c0328d012269f8741 / ViewState add-on before version 4.Fixed: version as tested: commit ac6c3f94d38505bc0facea286a4d3728044c6e5c / ViewState add-on version 4.

A materially distinct alternate trigger was confirmed on the vulnerable ZAP ViewState add-on: a malicious javax.faces.ViewState value in a proxied HTTP request body reaches the same JSFViewState.decode() / ObjectInputStream.readObject() sink through the add-on's request-panel factory. This differs from the parent reproduction, which used a malicious web server response body and the response-panel factory. However, this is not a bypass of the version 4 fix. The fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c disables the shared JSF ViewState registration in ViewStateModel, so both request and response panel paths stop before constructing JSFViewState.

Fix Coverage / Assumptions

The fix relies on the invariant that all normal add-on paths to JSF ViewState deserialization pass through ViewStateModel's constructor-populated viewstateParams list. The relevant patch comments out the only JSF parameter registration:

// viewstateParams.add(new ViewState(null, JSFViewState.KEY, "javax.faces.ViewState"));

This explicitly covers both ViewState panel factories because they instantiate the same model constructor:

  • ExtensionHttpPanelViewStateView.RequestSplitBodyViewStateViewFactory.getNewView() -> new ViewStateModel(ViewStateModel.VS_ACTION_REQUEST, null)
  • ExtensionHttpPanelViewStateView.ResponseSplitBodyViewStateViewFactory.getNewView() -> new ViewStateModel(ViewStateModel.VS_ACTION_RESPONSE, null)

The fix does not remove the dangerous sink itself: addOns/viewstate/src/main/java/org/zaproxy/zap/extension/viewstate/zap/utils/JSFViewState.java still contains unrestricted ObjectInputStream.readObject(). Therefore, future code that re-registers JSF ViewState or directly instantiates JSFViewState on untrusted proxied HTTP data would reintroduce the same root cause. Within the current fixed add-on panel surfaces, no gap was found.

No SECURITY.md or explicit serialization threat-model document was present in the inspected zap-extensions repository. The repository identifies ZAP as an HTTP/HTTPS proxy for assessing web application security, so proxied HTTP peer/message data was treated as crossing the relevant trust boundary. Direct local calls to parser classes were not treated as vulnerability variants.

Variant / Alternate Trigger

Tested alternate trigger:

  • Original parent surface: malicious HTTP response body from an attacker-controlled server -> ResponseSplitBodyViewStateViewFactory -> response HTML hidden-input parsing -> JSFViewState.decode().
  • Variant candidate surface: proxied HTTP request body containing javax.faces.ViewState=<serialized object> -> RequestSplitBodyViewStateViewFactory -> request parameter parsing and URL decoding -> JSFViewState.decode().

Exact entry point tested:

  • Entry point kind: proxied HTTP request body as represented by a real ZAP HttpMessage.
  • Request body: application/x-www-form-urlencoded body with javax.faces.ViewState set to a Base64 Java serialized object.
  • Product component path:
    1. ExtensionHttpPanelViewStateView$RequestSplitBodyViewStateViewFactory.getNewView()
    2. HttpPanelViewStateView
    3. DefaultHttpPanelViewModel.setMessage(HttpMessage)
    4. HttpPanelViewStateView.dataChanged()
    5. ViewStateModel.getData()
    6. ViewStateModel.getViewStateParam() request branch (StandardParameterParser + URLDecoder)
    7. JSFViewState.decode()
    8. ObjectInputStream.readObject()

The variant was confirmed on vulnerable commit 7e686c0900e82bb73b57880c0328d012269f8741 and blocked on fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c.

  • Package/component affected: zap-extensions, add-on addOns/viewstate / ZAP ViewState add-on.
  • Affected versions as tested: vulnerable parent 7e686c0900e82bb73b57880c0328d012269f8741 / ViewState add-on before version 4.
  • Fixed version as tested: commit ac6c3f94d38505bc0facea286a4d3728044c6e5c / ViewState add-on version 4.
  • Risk level and consequences on vulnerable versions: High. An attacker who can cause ZAP to proxy a request carrying a malicious JSF ViewState value can trigger Java deserialization in the ZAP process when the ViewState request panel processes the message, resulting in command execution with the ZAP user's privileges.
  • Fixed-version result: no RCE; the same request body was processed by the fixed request panel without JSF registration and without marker/RCE files.

Impact Parity

  • Disclosed/claimed maximum impact for parent: arbitrary code execution / RCE in ZAP through insecure JSF ViewState deserialization.
  • Reproduced impact from this variant run: command execution on the vulnerable commit. The payload wrote request_vuln_marker.txt and request_vuln_rce_output.txt, including RCE_VIA_ZAP_VIEWSTATE_REQUEST_VARIANT and id output from the deserializing JVM.
  • Parity: full for vulnerable-version alternate trigger; none on the fixed commit because the fix blocks the path.
  • Not demonstrated: a full GUI browser workflow that auto-submits a malicious form through a live ZAP desktop session. The proof instead drives the actual built add-on request-panel component with a real ZAP HttpMessage, which is the relevant product component boundary for this variant analysis.

Root Cause

The same root cause is reachable on vulnerable versions because ViewStateModel globally registered javax.faces.ViewState as JSF ViewState for both request and response models. In the request model (VS_ACTION_REQUEST), getViewStateParam() parses request parameters with StandardParameterParser, URL-decodes the matching value, constructs new JSFViewState(decVal, vsp.getName()), and getData() then calls vs.getDecodedValue(). For JSFViewState, this enters JSFViewState.decode() and calls unrestricted Java deserialization:

ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();

The fix commit is:

  • https://github.com/zaproxy/zap-extensions/commit/ac6c3f94d38505bc0facea286a4d3728044c6e5c

That commit disables the shared JSF registration rather than hardening JSFViewState.decode(). Because both request and response panel models use the same registration list, this alternate request-body trigger is blocked by the fix and is not a fixed-version bypass.

Reproduction Steps

  1. Use bundle/vuln_variant/reproduction_steps.sh.
  2. The script:
    • Resolves the vulnerable parent 7e686c0900e82bb73b57880c0328d012269f8741 and fixed commit ac6c3f94d38505bc0facea286a4d3728044c6e5c.
    • Builds the actual ViewState .zap add-on from both commits in isolated worktrees under bundle/vuln_variant/.
    • Compiles a Java harness that instantiates ExtensionHttpPanelViewStateView$RequestSplitBodyViewStateViewFactory from each built add-on.
    • Generates a Base64 Java serialized payload and places it in a URL-encoded request body parameter named javax.faces.ViewState.
    • Drives DefaultHttpPanelViewModel.setMessage(HttpMessage) on the request model.
    • Checks for marker/RCE output on the vulnerable build and confirms absence of those files on the fixed build.
  3. Expected outcome:
    • Script exits 1 because no fixed-version bypass is present.
    • Vulnerable evidence shows RequestSplitBodyViewStateViewFactory, ViewStateModel.has_jsf_registration=true, JSFViewState.decode, and marker/RCE files.
    • Fixed evidence shows ViewStateModel.has_jsf_registration=false, no marker file, and no RCE output file.

Evidence

Primary evidence files:

  • bundle/vuln_variant/reproduction_steps.sh — stage-specific reproduction script, executed twice successfully/idempotently.
  • bundle/logs/vuln_variant_reproduction_steps.log — full build and runtime transcript from the latest run.
  • bundle/logs/vuln_variant_request_vuln.log — vulnerable request-panel runtime evidence.
  • bundle/logs/vuln_variant_request_fixed.log — fixed request-panel negative-control runtime evidence.
  • bundle/logs/vuln_variant_build_vuln.log and bundle/logs/vuln_variant_build_fixed.log — Gradle build logs.
  • bundle/vuln_variant/runtime_manifest.json — runtime manifest for the variant candidate.
  • bundle/vuln_variant/artifacts/request_vuln_marker.txt — vulnerable marker with stack trace through the same sink.
  • bundle/vuln_variant/artifacts/request_vuln_rce_output.txt — command output from the vulnerable deserialization payload.
  • bundle/vuln_variant/artifacts/source_identity_request_variant.txt — tested commits and built archive hashes.

Key vulnerable excerpts:

[vuln] factory=org.zaproxy.zap.extension.viewstate.ExtensionHttpPanelViewStateView$RequestSplitBodyViewStateViewFactory
ViewStateModel.param name=javax.faces.ViewState type=JSF
ViewStateModel.has_jsf_registration=true
[vuln] marker_exists=true
[vuln] rce_output_exists=true

The vulnerable marker stack includes:

DESERIALIZATION_RCE_CONFIRMED_REQUEST_VARIANT
RCE_VIA_ZAP_VIEWSTATE_REQUEST_VARIANT
  at org.zaproxy.zap.extension.viewstate.zap.utils.JSFViewState.decode(JSFViewState.java:92)
  at org.zaproxy.zap.extension.viewstate.ViewStateModel.getData(ViewStateModel.java:183)
  at org.zaproxy.zap.extension.viewstate.HttpPanelViewStateView.dataChanged(HttpPanelViewStateView.java:189)
  at org.zaproxy.zap.extension.httppanel.view.DefaultHttpPanelViewModel.setMessage(DefaultHttpPanelViewModel.java:42)

Key fixed excerpts:

[fixed] factory=org.zaproxy.zap.extension.viewstate.ExtensionHttpPanelViewStateView$RequestSplitBodyViewStateViewFactory
ViewStateModel.param_count=2
ViewStateModel.param name=__VIEWSTATE type=ASP
ViewStateModel.param name=__VIEWSTATEFIELDCOUNT type=ASP
ViewStateModel.has_jsf_registration=false
[fixed] marker_exists=false
[fixed] rce_output_exists=false
[fixed] PASS: fixed request-panel did not deserialize malicious JSF ViewState

The default cached source was also inspected at commit c639b4e3fe10e472cbe8542de7fbe3964b4d4ce7; the javax.faces.ViewState registration remained commented out there.

Recommendations / Next Steps

  • Keep the version 4 fix that disables JSF support; it covers both request and response ViewState panel paths.
  • Add regression tests for both RequestSplitBodyViewStateViewFactory and ResponseSplitBodyViewStateViewFactory that feed javax.faces.ViewState serialized-object-looking data and assert that JSFViewState.decode() is not reached.
  • For defense in depth, remove JSFViewState.decode()'s unrestricted ObjectInputStream.readObject() implementation or guard it with a strict JEP 290 ObjectInputFilter and a very small allowlist if JSF parsing is ever restored.
  • Audit future changes for any reintroduction of new ViewState(... JSFViewState.KEY, "javax.faces.ViewState") or direct use of JSFViewState on proxied HTTP data.

Additional Notes

  • Idempotency confirmed: bundle/vuln_variant/reproduction_steps.sh was run twice. Both runs completed without crashing and exited 1, which is the expected script result for “alternate trigger on vulnerable version only; no fixed-version bypass.”
  • The prepared repository worktree itself was not checked out or mutated in place for testing; isolated worktrees under bundle/vuln_variant/build_request_variant/worktrees/ were used.
  • The repository lacked an explicit SECURITY.md; no target policy was found that excluded proxied HTTP message parsing from security scope.

CVE-2026-57527 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:11
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-57527 · REPRO-20
0:03
0:04
web search
0:05
web search
0:08
0:10
0:12
0:16
0:18
0:38
0:38
extract_facts
no facts extracted
0:40
0:40
0:40
supportrepro
0:53
0:55
0:55
0:55
0:56
0:56
0:56
0:56
0:59
1:00
1:01
web search
1:04
1:06
1:06
$ls -la /data/pruva/project-cache/a032c641-95cb-4a13-867e-d136b678d029/repo-mirrors/ 2>/dev/null; echo "---"; cat /data/pruva/project-cache/a032c641-95cb-4a13-867e-d136b678d029/repo-mirrors/*.txt 2>/dev/null; echo "---check repo dirs---"; find /data/pruva/project-cache/a032c641-95cb-4a13-867e-d136b678d029 -maxdepth 2 -type d 2>/dev/null
total 0
drwxr-xr-x 1 vscode vscode  0 Jul  5 07:06 .
drwxr-xr-x 1 vscode vscode 24 Jul  5 07:06 ..
---
---check repo dirs---
/data/pruva/project-cache/a032c641-95cb-4a13-867e-d136b678d029
/data/pruva/project-cache/a032c641-95cb-4a13-867e-d136b678d029/repo-mirrors
1:11

Artifacts and Evidence for CVE-2026-57527

Scripts, logs, diffs, and output captured during the reproduction.

bundle/artifact_promotion_manifest.json16.3 KB
bundle/vuln_variant/source_identity.json1.8 KB
bundle/vuln_variant/root_cause_equivalence.json1.7 KB
bundle/repro/reproduction_steps.sh26.6 KB
bundle/repro/artifacts/marker_vuln.txt0.3 KB
bundle/repro/artifacts/rce_output.txt0.1 KB
bundle/repro/artifacts/fix.patch3.0 KB
bundle/repro/runtime_manifest.json1.5 KB
bundle/repro/validation_verdict.json0.8 KB
bundle/repro/rca_report.md11.2 KB
bundle/logs/vuln_harness_1.log3.9 KB
bundle/logs/reproduction_steps.log17.8 KB
bundle/repro/artifacts/vuln_marker_1.txt2.4 KB
bundle/repro/artifacts/source_identity.txt0.6 KB
bundle/logs/build_vuln.log3.2 KB
bundle/logs/build_fixed.log3.2 KB
bundle/logs/vuln_harness_2.log3.9 KB
bundle/logs/fixed_harness_1.log1.3 KB
bundle/logs/fixed_harness_2.log1.3 KB
bundle/logs/server_vuln_1.log0.2 KB
bundle/logs/server_vuln_2.log0.2 KB
bundle/logs/server_fixed_1.log0.2 KB
bundle/logs/server_fixed_2.log0.2 KB
bundle/repro/artifacts/product_path_harness.java6.9 KB
bundle/repro/artifacts/payload.b640.4 KB
bundle/repro/artifacts/vuln_marker_2.txt2.4 KB
bundle/repro/artifacts/vuln_rce_output_1.txt0.1 KB
bundle/repro/artifacts/vuln_rce_output_2.txt0.1 KB
bundle/vuln_variant/reproduction_steps.sh20.7 KB
bundle/vuln_variant/rca_report.md11.2 KB
bundle/vuln_variant/patch_analysis.md7.5 KB
bundle/vuln_variant/variant_manifest.json4.9 KB
bundle/vuln_variant/validation_verdict.json3.1 KB
bundle/vuln_variant/runtime_manifest.json1.5 KB
bundle/logs/vuln_variant_reproduction_steps.log10.7 KB
bundle/logs/vuln_variant_request_vuln.log3.9 KB
bundle/logs/vuln_variant_request_fixed.log1.3 KB
bundle/vuln_variant/artifacts/request_vuln_marker.txt2.4 KB
bundle/logs/vuln_variant_build_vuln.log3.2 KB
bundle/logs/vuln_variant_build_fixed.log3.2 KB
bundle/vuln_variant/artifacts/request_variant_harness.java5.8 KB
bundle/vuln_variant/artifacts/request_payload_vuln.b640.4 KB
bundle/vuln_variant/artifacts/request_payload_fixed.b640.4 KB
bundle/vuln_variant/artifacts/request_vuln_rce_output.txt0.1 KB
bundle/vuln_variant/artifacts/source_identity_request_variant.txt0.7 KB
08 · How to Fix

How to Fix CVE-2026-57527

Upgrade zaproxy/zap-extensions · github to ViewState add-on version 4 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-57527 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-57527

How does the CVE-2026-57527 ViewState deserialization attack work?

An attacker who controls a web server that a ZAP user proxies through returns an HTTP response containing a hidden javax.faces.ViewState field whose value is a Base64-encoded malicious serialized Java object. When ZAP's ViewState add-on parses the response and deserializes that field with ObjectInputStream.readObject(), the attacker's object graph executes with the privileges of the ZAP process.

Which versions of the ZAP ViewState add-on are affected by CVE-2026-57527, and where is it fixed?

ViewState add-on versions 1, 2, and 3 (before version 4) are affected. It is fixed in ViewState add-on version 4.

How severe is CVE-2026-57527?

High severity -- arbitrary code execution inside the ZAP JVM, triggered simply by a security tester proxying or viewing a malicious page through a vulnerable ZAP install.

How can I reproduce CVE-2026-57527?

Download the verified script from this page and run it in an isolated environment against ZAP with the ViewState add-on before version 4. It stands up a malicious server that returns a crafted javax.faces.ViewState value, proxies a request through ZAP, and confirms the resulting Java deserialization executes an attacker-chosen command inside the ZAP process.
11 · References

References for CVE-2026-57527

Authoritative sources for CVE-2026-57527 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.