Skip to content

CVE-2026-57527: Verified Reproduction

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 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://www.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
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.

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
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.