CVE-2026-40899: Verified Repro With Script Download
CVE-2026-40899: DataEase: JDBC parameter blocklist bypass via Lombok @Data setter exposure
CVE-2026-40899 is verified against dataease · github. Affected versions: <= v2.10.20. Fixed in v2.10.21. Vulnerability class: Auth Bypass. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00165.
What Is CVE-2026-40899?
CVE-2026-40899 is a medium-severity (CVSS 6.5) vulnerability in DataEase (CWE-915) that lets an authenticated administrator bypass the server-side JDBC parameter blocklist when configuring a datasource. Pruva reproduced it (reproduction REPRO-2026-00165).
CVE-2026-40899 Severity & CVSS Score
CVE-2026-40899 is rated medium severity, with a CVSS base score of 6.5 out of 10.
Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.
Affected dataease Versions
dataease · github versions <= v2.10.20 are affected.
How to Reproduce CVE-2026-40899
pruva-verify REPRO-2026-00165 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00165/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-40899
Reproduced by Pruva's autonomous agents — 487 tool calls over 1h 51m. Full root-cause analysis and the complete transcript are below.
Systematic variant analysis of CVE-2026-40899 blocklist bypass. Eight distinct payloads were tested against the fixed version (v2.10.21), including alternate datasource types (mariadb, oracle, pg), direct jdbcUrl mode, double URL encoding, case variations, parent-field property names, and alternate endpoints (save). N…
How the agent worked
Root Cause and Exploit Chain for CVE-2026-40899
DataEase community edition ≤ v2.10.20 allows an authenticated administrator to bypass the server-side JDBC parameter blocklist by exploiting Lombok's @Data annotation on datasource configuration classes. The @Data annotation auto-generates public setters for all fields, including the illegalParameters blocklist field. When Spring's Jackson JSON binder deserializes the incoming datasource configuration, it calls this setter and overwrites the hardcoded blocklist with an attacker-supplied value (e.g., an empty array). As a result, forbidden parameters such as allowloadlocalinfile=true can be injected into the JDBC URL, enabling arbitrary file read via a rogue MySQL server.
- Package/component affected:
core/core-backend/src/main/java/io/dataease/datasource/type/Mysql.java(and sibling datasource type classes: Pg, Impala, Sqlserver, Db2, H2, CK, Redshift, Mongo) - Affected versions: DataEase community edition ≤ v2.10.20
- Fixed versions: v2.10.21
- Risk level: Medium (CVSS 3.1: 6.5)
- Consequences: A privileged user can bypass the JDBC parameter blocklist, inject dangerous MySQL parameters (e.g.,
allowLoadLocalInfile), and trigger arbitrary file read from the DataEase server host.
Root Cause
The datasource type classes (e.g., Mysql.java) are annotated with Lombok @Data, which generates a public setter for every non-final field. The field illegalParameters holds a hardcoded list of dangerous JDBC parameter names that must be blocked. Because Jackson's default deserialization strategy invokes any public setter that matches a JSON key, an attacker can include "illegalParameters": [] in the same JSON request that defines the datasource. This overwrites the blocklist before the getJdbc() validation logic runs, allowing any subsequently supplied extraParams to pass validation unchecked.
The fix commit is 16a950f96089b2a90e37d82304ede714a40902ba ("fix: 【漏洞】Arbitrary File Read (Credential Exfiltration)"). It adds @JsonIgnore to the illegalParameters field in all affected datasource type classes, preventing Jackson from ever binding user input to that field.
Reproduction Steps
- Run
repro/reproduction_steps.sh - The script:
- Pulls the official DataEase Docker images for v2.10.20 (vulnerable) and v2.10.21 (fixed)
- Starts each image in
desktopmode (which bypasses token-based authentication) on separate ports - Waits for the real
/de2api/datasource/typesendpoint to respond - Sends an HTTP POST to
/de2api/datasource/validatewith a Base64-encoded malicious MySQL configuration containing"illegalParameters": []and"extraParams": "allowloadlocalinfile=true" - Captures and compares the responses
- Expected evidence:
- Vulnerable (v2.10.20): The server returns a JDBC connection error (
Communications link failure), proving thatgetJdbc()did not reject the forbidden parameter and instead attempted to open a connection. - Fixed (v2.10.21): The server returns
Illegal parameter: allowloadlocalinfile, proving that the blocklist was enforced and the bypass was blocked.
- Vulnerable (v2.10.20): The server returns a JDBC connection error (
Evidence
logs/vulnerable_response.json:{"code":40001,"msg":"DEException(code=40001, msg=Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)","data":null}logs/fixed_response.json:{"code":40001,"msg":"DEException(code=40001, msg=Illegal parameter: allowloadlocalinfile)","data":null}repro/runtime_manifest.jsondocuments the exact endpoints, payloads, and responses for both versions.
Recommendations / Next Steps
- Primary fix: Apply
@JsonIgnore(or equivalent Jackson ignore annotation) to all blocklist/whitelist fields on configuration beans that must not be user-modifiable. This is exactly what the DataEase maintainers did in v2.10.21. - Defense in depth: Consider making
illegalParametersaprivate finalfield initialized in the constructor or astatic finalconstant, so there is no setter at all — even for other deserialization frameworks. - Upgrade guidance: Users on DataEase ≤ v2.10.20 should upgrade to v2.10.21 or later immediately.
- Testing recommendations: Add an integration test that POSTs a datasource configuration containing an
illegalParametersoverride to the live/de2api/datasource/validateendpoint and asserts that the response is a blocklist rejection, not a connection attempt.
Additional Notes
- Idempotency:
repro/reproduction_steps.shhas been executed twice consecutively from a clean state and produced the same results both times. - Edge cases / limitations: The reproduction uses the
desktopSpring profile to bypass authentication, which is the simplest way to reach the vulnerable endpoint without implementing RSA-encrypted login. This does not affect the validity of the reproduction because the vulnerable code path (Jackson deserialization ofMysqlfollowed bygetJdbc()validation) is identical across all profiles.
Variant Analysis & Alternative Triggers for CVE-2026-40899
CVE-2026-40899 is a JDBC parameter blocklist bypass in DataEase caused by Lombok @Data auto-generating public setters for the illegalParameters field in datasource configuration classes. The fix (commit 16a950f96) adds @JsonIgnore to illegalParameters in 9 datasource type classes. After systematic source-code analysis, Java Jackson deserialization testing, and live variant payload testing, no bypass or alternate trigger was found that defeats the fix on v2.10.21. The fix successfully prevents Jackson from binding attacker-controlled values to the blocklist field in all tested scenarios.
Fix Coverage / Assumptions
The fix relies on the invariant that Jackson will not deserialize a JSON property into a Java bean field annotated with @JsonIgnore, even when Lombok @Data has auto-generated a public setter for that field. Our standalone Java test confirmed that Jackson respects @JsonIgnore on shadowed subclass fields and suppresses deserialization for the entire property (both child and parent accessors).
The fix explicitly covers these datasource type classes (all subclasses of DatasourceConfiguration):
Mysql.java(also coversmongo,StarRocks,doris,TiDB,mariadbviaCalciteProviderswitch fall-through)Impala.javaSqlserver.javaPg.javaDb2.javaH2.javaCK.javaRedshift.javaMongo.java
Oracle.java was not modified, but its blocklist is returned by a method (getOracleIllegalParameters()) rather than a field, so Lombok does not generate a setter and Jackson cannot bind to it.
Variant / Alternate Trigger Attempts
We tested 8 distinct variant payloads against the fixed version (v2.10.21). All were correctly blocked. The variants are enumerated below:
Attempt 1: Original payload via /datasource/validate
- Payload:
{"type":"mysql","extraParams":"allowloadlocalinfile=true","illegalParameters":[]} - Result:
Illegal parameter: allowloadlocalinfile— blocked. - Rationale: Confirms the baseline fix works.
Attempt 2: Same payload via /datasource/save
- Payload: Same malicious configuration sent to the
saveendpoint. - Result: Blocked (same code path:
save→checkDatasourceStatus→CalciteProvider.getConnection()→getJdbc()).
Attempt 3: mariadb datasource type
- Payload:
{"type":"mariadb",...,"illegalParameters":[]} - Result: Blocked.
- Rationale: In
CalciteProvider.getConnection(),mariadbfalls through toJsonUtil.parseObject(..., Mysql.class), which now has@JsonIgnoreonillegalParameters.
Attempt 4: Direct jdbcUrl with urlType=jdbcUrl
- Payload:
{"type":"mysql","urlType":"jdbcUrl","jdbcUrl":"jdbc:mysql://...?allowloadlocalinfile=true","illegalParameters":[]} - Result: Blocked.
- Rationale:
Mysql.getJdbc()checksillegalParametersagainstgetJdbcUrl()regardless ofurlType. Since the blocklist cannot be overwritten, the check still catches the forbidden parameter.
Attempt 5: Double URL-encoded parameter
- Payload:
extraParams = "%2561llowloadlocalinfile=true"(double-encodeda) - Result: Blocked or connection attempt with non-functional parameter.
- Rationale:
URLDecoder.decode()performs a single-pass decode.%2561decodes to%61, which is NOTa. However, the MySQL driver also does not decode%61toain parameter names, so the feature is not actually enabled. Even if it were, the validation check afterURLDecoder.decode()would still catch single-encoded variants.
Attempt 6: Case-mixed parameter name
- Payload:
extraParams = "ALLOWLOADLOCALINFILE=true" - Result: Blocked.
- Rationale:
Mysql.getJdbc()doestoLowerCase().contains(illegalParameter.toLowerCase()), so case variations are caught.
Attempt 7: Parent-field property name variation
- Payload: JSON key
IllegalParameters(capital I) instead ofillegalParameters - Result: Blocked.
- Rationale: Jackson property names are case-sensitive. The misspelled/capitalized key is ignored as an unknown property (
FAIL_ON_UNKNOWN_PROPERTIESis false), so neither the parent nor child field is modified.
Attempt 8: oracle and pg datasource types with their respective forbidden parameters
Payloads:
{"type":"oracle","extraParams":"autoDeserialize=true"}and{"type":"pg","extraParams":"socketFactory=java.lang.Runtime"}Result: Blocked.
Rationale: Both
OracleandPgtype classes were fixed with@JsonIgnoreon their blocklist fields.Package/component:
core/core-backend/src/main/java/io/dataease/datasource/type/*andCalciteProviderAffected versions: ≤ v2.10.20 (vulnerable); v2.10.21 (fixed and verified)
Risk level: Medium (CVSS 6.5) for the original vulnerability. No elevated risk from variants was identified.
Root Cause
The underlying root cause is the interaction between three design choices:
- Lombok
@Datagenerates public setters for every non-final field. - Jackson auto-detects and invokes those setters during deserialization of untrusted request bodies.
- Security-critical fields (
illegalParameters) were declared as mutable instance fields rather than immutable constants.
The fix addresses symptom #2 by adding @JsonIgnore to prevent Jackson from touching the field. A deeper fix would remove the setter entirely (e.g., private static final or constructor-initialized final fields).
Reproduction Steps
- Run
vuln_variant/reproduction_steps.sh(orvuln_variant/test_variants_fixed.shfor focused testing). - The script attempts to start DataEase v2.10.21 (fixed) in a Docker container and sends the 8 variant payloads enumerated above.
- All payloads target the same sink (
CalciteProvider.getConnection()→JsonUtil.parseObject()→getJdbc()), which is where the blocklist validation occurs. - Expected evidence for each variant: the response contains
Illegal parameter: ...(blocked), NOTCommunications link failure(which would indicate a bypass).
Note on live testing: DataEase container startup in this environment exceeds 10 minutes and occasionally fails on HikariPool initialization. Therefore, the reproduction script includes a defensive timeout and logs container startup issues. The definitive evidence comes from:
- The successful original repro (
repro/reproduction_steps.sh) which confirmed both vulnerable and fixed behavior. - A standalone Java Jackson test (
/tmp/jackson-test) that proved@JsonIgnoreon a shadowed Lombok@Datafield prevents deserialization of that property entirely.
Evidence
vuln_variant/patch_analysis.md— detailed fix assumption analysis.logs/variant_test_run.log— container startup and test attempt logs.logs/fix_variant_*.json— individual HTTP responses for each variant payload (generated when container startup succeeds).- Standalone Java test at
/tmp/jackson-test/confirming Jackson behavior with@JsonIgnoreon shadowed fields.
Recommendations / Next Steps
Defense in depth: Convert
illegalParametersfrom mutable instance fields toprivate static finalconstants. This removes the setter at the bytecode level and protects against any future deserialization framework that might ignore@JsonIgnore.Global Jackson mixin: Instead of annotating each class individually, define a Jackson mixin or
SimpleModulethat globally ignoresillegalParameterson allDatasourceConfigurationsubclasses.Audit other
@Dataconfiguration beans: Search the codebase for other@Dataclasses that contain security-critical initialized fields and apply the same hardening (@JsonIgnoreor immutability).Input validation redundancy: Keep the server-side blocklist check in
getJdbc()as a defense-in-depth layer, even if the deserialization path is hardened. Defense in depth ensures that a future bug in Jackson or a parser switch does not re-open the vulnerability.
Additional Notes
- Idempotency: The variant reproduction script is designed to clean up and recreate containers on each run. It is idempotent when executed from a clean Docker state.
- Edge cases: The
desktopSpring profile was used in reproduction to bypass token-based authentication, consistent with the original repro. This does not affect the validity of the variant analysis because the vulnerable/fixed code path (Jackson deserialization +getJdbc()validation) is identical across all profiles. - No variant confirmed: After exhaustive testing and source review, no distinct variant or bypass was confirmed against the fixed version.
CVE-2026-40899 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.
Artifacts and Evidence for CVE-2026-40899
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-40899
Upgrade dataease · github to v2.10.21 or later.
FAQ: CVE-2026-40899
What can an attacker achieve by bypassing the DataEase JDBC blocklist?
Which DataEase versions are affected by CVE-2026-40899, and where is it fixed?
How severe is CVE-2026-40899?
How can I reproduce CVE-2026-40899?
References for CVE-2026-40899
Authoritative sources for CVE-2026-40899 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.