Skip to content

fix(security): upgrade arangodb-java-driver to 7.25.0 to remediate CVE-2025-52999#41789

Open
subrata71 wants to merge 1 commit intoreleasefrom
fix/cve-2025-52999-jackson-core
Open

fix(security): upgrade arangodb-java-driver to 7.25.0 to remediate CVE-2025-52999#41789
subrata71 wants to merge 1 commit intoreleasefrom
fix/cve-2025-52999-jackson-core

Conversation

@subrata71
Copy link
Copy Markdown
Collaborator

@subrata71 subrata71 commented May 9, 2026

Summary

Remediates CVE-2025-52999 (jackson-core deeply-nested-JSON DoS, CVSS 8.7 High) in the arangoDBPlugin runtime by upgrading the parent library that bundles the vulnerable jackson-core, rather than overriding the transitive dependency.

Root cause (verified)

arangodb-java-driver:6.12.3 (June 2021, EOL) transitively pulls com.arangodb:velocypack:2.5.3, which shades a relocated copy of com.fasterxml.jackson.core:jackson-core:2.11.3 at the package path com.arangodb.velocypack.deps.com.fasterxml.jackson inside the velocypack jar. The relocated META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.properties declares version=2.11.3 — that is what Docker Scout detects at /opt/appsmith/server/mongo/plugins/arangodbPlugin-1.0-SNAPSHOT/lib/. velocypack uses these shaded classes to convert ArangoDB responses on the parsing path, so a deeply-nested JSON payload from a user-configured ArangoDB server can trigger StackOverflowError per the original customer justification.

Fix approach (industry-standard, no transitive override)

Upgrade the parent library: arangodb-java-driver 6.12.37.25.0 (Jan 2026, latest stable). Driver 7.x:

  • Removes velocypack from the default transitive set (only used when HTTP_VPACK content type is selected, which we no longer use after switching to the v7 default HTTP2_JSON). The shaded vulnerable jar disappears entirely.
  • Ships plain jackson-core:2.20.0 via the com.arangodb:jackson-serde-json module, resolved to 2.17.0 after parent-managed jackson-bom.version. Both are well above the 2.15.0 fix threshold.
  • Auto-configures Jackson StreamReadConstraints (added in driver 7.5.0) as defense-in-depth, directly hardening the per-request DoS vector named in the customer justification.

No <dependencyManagement> overrides, no transitive pinning, no shading workarounds.

Changes

  • pom.xml — bump driver 6.12.37.25.0; drop now-unused org.apache.httpcomponents:httpclient (v7 uses Vert.x WebClient internally; verified zero direct usages in plugin source via rg "org\.apache\.http").
  • ArangoDBPlugin.java — migrate to v7 API:
    • db.query(query, null, null, Map.class)db.query(query, Map.class, null, null) (parameter order changed in v7)
    • useProtocol(...)protocol(...) (renamed in v7)
    • Protocol.HTTP_VPACKProtocol.HTTP2_JSON (the v7 default; avoids needing the jackson-serde-vpack extra module)
    • Register a custom JacksonSerde with USE_LONG_FOR_INTS so query results preserve Long for integer values, matching v6 VPACK behavior. This keeps the structure-tree column types stable for users (e.g., a small integer like age=20 still surfaces as Long, not Integer).
  • ArangoDBErrorUtils.java — walk the cause chain for UnknownHostException and also detect the v7 Cannot contact any host message, so the user-visible bad-host error message stays the same as v6.
  • ArangoDBPluginTest.java — align fixture with the protocol/serde change; replace test-fixture LocalDate.of(...) with a Map matching the test's own JSON Schema, and BigDecimal(...) with a String for the currency field (more realistic; doesn't depend on driver wire-format quirks). No production impact.

Validation

mvn dependency:tree — vulnerable deps absent

+- com.arangodb:arangodb-java-driver:jar:7.25.0:compile
|  +- com.arangodb:core:jar:7.25.0:compile
|  |  +- com.fasterxml.jackson.core:jackson-core:jar:2.17.0:compile
|  +- com.arangodb:http-protocol:jar:7.25.0:compile
|  \- com.arangodb:jackson-serde-json:jar:7.25.0:compile

velocypack is no longer present. jackson-core:2.17.0 (above the 2.15.0 fix threshold).

Runtime lib/ jar scan — vulnerable shaded copy gone

$ for j in target/lib/*.jar; do
    unzip -p "$j" META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.properties 2>/dev/null
  done | grep -c version=2.11.3
0   # zero jars contain shaded jackson-core 2.11.3

The only jackson-core/pom.properties in lib/ now belongs to the un-shaded jackson-core-2.17.0.jar itself.

Tests — all green

  • mvn -pl appsmith-plugins/arangoDBPlugin -am test: 207/207 passing (181 from interfaces parent + 26 from the plugin module, including the 4 testcontainer-backed end-to-end ArangoDB integration tests against arangodb/arangodb:3.7.12 — connect, read AQL, write AQL with writesExecuted/Ignored, and structure discovery).
  • Live smoke test against arangodb/arangodb:3.11.14: all four production code paths exercised; numeric values come back as Long as before; string values remain String.

CE→EE sync simulation

Cherry-pick simulation shows a small mechanical conflict in the import block of ArangoDBPlugin.java (EE has additional Jackson imports for its EE-only getConfigurationContent method). Resolution is a union of imports. A pre-staged shadow EE PR with the resolved version will be opened immediately after this CE PR.

Test plan

  • CI passes on this PR (server build + spotless + unit/integration tests).
  • Docker Scout rescan after the official EE image build no longer flags CVE-2025-52999.
  • Manual: configure an ArangoDB datasource in a deployed Appsmith, run an AQL RETURN query, verify result shape and structure-tree column types match pre-fix (numeric → Long).
  • Manual: trigger a bad host configuration and confirm the friendly "Could not find host address..." error still appears.

Refs: CVE-2025-52999, customer-shared "Affected, fix planned" justification.

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection and user-facing messaging for unreachable ArangoDB hosts.
  • Chores

    • Upgraded the ArangoDB Java driver to a newer major version, improving compatibility and result handling; corresponding tests and test data were updated.

Review Change Stack

Caution

🔴 🔴 🔴 Some tests have failed.
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/25637088241
Commit: a15e212
Cypress dashboard.
Tags: @tag.All
Spec:
The following are new failures, please fix them before merging the PR:

  1. cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts
List of identified flaky tests.
Mon, 11 May 2026 02:23:34 UTC

Automation

/ok-to-test tags="@tag.All"

@subrata71 subrata71 requested a review from sharat87 as a code owner May 9, 2026 19:27
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

Walkthrough

ArangoDB Java Driver upgraded to 7.25.0. Query calls updated to new overloads using Map.class earlier. Client switched from HTTP_VPACK to HTTP2_JSON with a JacksonSerde using USE_LONG_FOR_INTS. Error detection now walks Throwable causes for host failures. Tests updated for API changes.

Changes

ArangoDB Driver 7.x Upgrade

Layer / File(s) Summary
Dependency Upgrade
app/server/appsmith-plugins/arangoDBPlugin/pom.xml
com.arangodb:arangodb-java-driver upgraded to version 7.25.0; existing slf4j-api exclusion preserved.
Client Configuration
app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/plugins/ArangoDBPlugin.java
Imports adjusted; ArangoDB builder switches to Protocol.HTTP2_JSON and sets a JacksonSerde with DeserializationFeature.USE_LONG_FOR_INTS.
Query API Migration
app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/plugins/ArangoDBPlugin.java
Query execution and structure retrieval updated to db.query(query, Map.class, null, null) signature (result type parameter moved earlier).
Error Handling
app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/utils/ArangoDBErrorUtils.java
UnknownHostException import added; error detection traverses Throwable causes and also matches "Cannot contact any host".
Test Updates
app/server/appsmith-plugins/arangoDBPlugin/src/test/java/com/external/plugins/ArangoDBPluginTest.java
Embedded client configured with Protocol.HTTP2_JSON; collection schema API changed to schema(...); test document fields changed to avoid LocalDate/BigDecimal.

🎯 3 (Moderate) | ⏱️ ~20 minutes


Driver seven lands, a protocol reborn,
Maps go first where types are sworn,
Hosts are traced through cause and thread,
Tests now match the JSON spread,
A small upgrade — smooth onward! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: upgrading arangodb-java-driver to 7.25.0 to fix CVE-2025-52999, which is the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description comprehensively documents the CVE fix, root cause analysis, approach, code changes, validation, and test plan with clear technical depth.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cve-2025-52999-jackson-core

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@subrata71 subrata71 self-assigned this May 9, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/server/appsmith-plugins/arangoDBPlugin/src/test/java/com/external/plugins/ArangoDBPluginTest.java (1)

152-165: ⚡ Quick win

Assert the Long coercion on the read path.

These fixtures now set up the JSON integer case that USE_LONG_FOR_INTS is meant to preserve, but the read-query assertions still only check asText(). That would keep passing if deserialization regressed back to Integer, so the main compatibility goal of this PR is not directly covered in CI.

🧪 Suggested assertion for testExecuteReadQuery()
+import com.fasterxml.jackson.core.JsonParser;
...
                     assertEquals("Kierra Gentry", node.get("name").asText());
                     assertEquals("F", node.get("gender").asText());
                     assertEquals("40", node.get("age").asText());
+                    assertEquals(JsonParser.NumberType.LONG, node.get("age").numberType());
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/server/appsmith-plugins/arangoDBPlugin/src/test/java/com/external/plugins/ArangoDBPluginTest.java`
around lines 152 - 165, The test currently inserts a large integer (luckyNumber
= 987654321L) but only asserts the read result via asText(); update
testExecuteReadQuery to explicitly assert the numeric field is deserialized as a
Long on the read path (e.g., retrieve the node/result for "luckyNumber" and
assert its Java type or value equals a Long with the same value), ensuring the
fixture from collection.insertDocuments triggers USE_LONG_FOR_INTS behavior and
the assertion fails if deserialization reverts to Integer.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/utils/ArangoDBErrorUtils.java`:
- Around line 71-74: The current check in ArangoDBErrorUtils that maps errors to
DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG uses the generic "Cannot contact any
host" string and thus collapses all connectivity failures into an "invalid
hostname" error; update the logic in ArangoDBErrorUtils (the block that inspects
externalErrorMessage and sets DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG) to only
treat true DNS/name-resolution failures as hostname errors by: 1) inspecting the
exception cause chain (externalError.getCause() recursively) for an actual
UnknownHostException type, and 2) matching only DNS-specific textual signals
(e.g., "UnknownHostException", "Name or service not known", "nodename nor
servname", etc.), and stop using a blanket match on "Cannot contact any host".

---

Nitpick comments:
In
`@app/server/appsmith-plugins/arangoDBPlugin/src/test/java/com/external/plugins/ArangoDBPluginTest.java`:
- Around line 152-165: The test currently inserts a large integer (luckyNumber =
987654321L) but only asserts the read result via asText(); update
testExecuteReadQuery to explicitly assert the numeric field is deserialized as a
Long on the read path (e.g., retrieve the node/result for "luckyNumber" and
assert its Java type or value equals a Long with the same value), ensuring the
fixture from collection.insertDocuments triggers USE_LONG_FOR_INTS behavior and
the assertion fails if deserialization reverts to Integer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 489fc5f9-9fdb-4338-9201-f2dda6020938

📥 Commits

Reviewing files that changed from the base of the PR and between 893572e and ef9e0a5.

📒 Files selected for processing (4)
  • app/server/appsmith-plugins/arangoDBPlugin/pom.xml
  • app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/plugins/ArangoDBPlugin.java
  • app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/utils/ArangoDBErrorUtils.java
  • app/server/appsmith-plugins/arangoDBPlugin/src/test/java/com/external/plugins/ArangoDBPluginTest.java

Comment on lines +71 to +74
String externalErrorMessage = externalError.getMessage();
if (externalErrorMessage != null
&& (externalErrorMessage.contains("UnknownHostException")
|| externalErrorMessage.contains("Cannot contact any host"))) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In arangodb-java-driver 7.x, is the top-level message "Cannot contact any host" specific to UnknownHostException, or is it also used for other connection failures such as timeouts, TLS handshake failures, or connection refused?

💡 Result:

In arangodb-java-driver 7.x, the top-level message “Cannot contact any host” / “Was not able to connect to any host” is not specific to UnknownHostException. It is a general “all hosts failed” wrapper that can be thrown for multiple kinds of connection failures (e.g., DNS/host reachability problems as well as other TCP/SSL/connectivity issues). Evidence: - When ArangoDB is unreachable, users report the driver throwing com.arangodb.ArangoDBException with message “Was not able to connect to any host” after connection attempts fail (alongside lower-level connection exceptions like ConnectException). [1] - In that same report, the lower-level failure can include “or SSL Handshake failed”, demonstrating that the driver’s top-level “connect to any host” failure is used even when the underlying cause is SSL/TLS handshake failure—not just DNS/UnknownHostException. [1] - The driver’s host failover behavior is designed around “first host is used … When this host is not reachable the next host … is used,” which implies the final “any host” failure is about reachability/connection establishment broadly, not a single exception type. [2] So, you should treat “Cannot contact any host” as “the driver could not establish a connection to any configured host,” and inspect the underlying cause/stacktrace/logs for the specific failure (UnknownHostException vs timeouts vs TLS handshake vs connection refused). The driver has changed its HTTP client to Vert.x WebClient in v7, but the existence of this generic wrapper behavior is evidenced by the reported exception handling. [3][2][1]

Citations:


Don't collapse the generic v7 connectivity error into "invalid hostname".

The message "Cannot contact any host" is a generic wrapper used by arangodb-java-driver 7.x for all connection failures—not just DNS issues. It covers SSL/TLS handshake failures, timeouts, connection refused, and general host reachability problems. With this fallback, these non-hostname errors will be rewritten to DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG whenever the underlying cause type is lost in wrapping.

🔎 Narrow the fallback to DNS-specific signals only
-            if (externalErrorMessage != null
-                    && (externalErrorMessage.contains("UnknownHostException")
-                            || externalErrorMessage.contains("Cannot contact any host"))) {
+            if (externalErrorMessage != null && externalErrorMessage.contains("UnknownHostException")) {
                 return DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
String externalErrorMessage = externalError.getMessage();
if (externalErrorMessage != null
&& (externalErrorMessage.contains("UnknownHostException")
|| externalErrorMessage.contains("Cannot contact any host"))) {
String externalErrorMessage = externalError.getMessage();
if (externalErrorMessage != null && externalErrorMessage.contains("UnknownHostException")) {
return DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/server/appsmith-plugins/arangoDBPlugin/src/main/java/com/external/utils/ArangoDBErrorUtils.java`
around lines 71 - 74, The current check in ArangoDBErrorUtils that maps errors
to DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG uses the generic "Cannot contact any
host" string and thus collapses all connectivity failures into an "invalid
hostname" error; update the logic in ArangoDBErrorUtils (the block that inspects
externalErrorMessage and sets DS_HOSTNAME_MISSING_OR_INVALID_ERROR_MSG) to only
treat true DNS/name-resolution failures as hostname errors by: 1) inspecting the
exception cause chain (externalError.getCause() recursively) for an actual
UnknownHostException type, and 2) matching only DNS-specific textual signals
(e.g., "UnknownHostException", "Name or service not known", "nodename nor
servname", etc.), and stop using a blanket match on "Cannot contact any host".

…E-2025-52999

CVE-2025-52999 (jackson-core deeply-nested-JSON DoS, CVSS 8.7) was reachable
through the arangoDBPlugin runtime because arangodb-java-driver 6.12.3
transitively pulled in com.arangodb:velocypack:2.5.3, which shades a relocated
copy of com.fasterxml.jackson.core:jackson-core:2.11.3 inside its jar. The
shaded classes were used by velocypack to convert ArangoDB responses, so a
deeply-nested JSON payload from a user-configured ArangoDB server could trigger
StackOverflowError on the parsing thread.

Industry-standard remediation: upgrade the parent library, not the transitive.
Driver 7.25.0 removes velocypack from the default transitive set, so the
shaded vulnerable jar disappears entirely. The replacement runtime classpath
ships jackson-core 2.17.0 (un-shaded, well above the 2.15.0 fix threshold).
Driver 7.5.0+ also auto-configures Jackson StreamReadConstraints as
defense-in-depth, directly hardening the per-request DoS vector.

Changes:
- pom.xml: bump arangodb-java-driver 6.12.3 -> 7.25.0; drop unused
  org.apache.httpcomponents:httpclient (v7 uses Vert.x WebClient internally)
- ArangoDBPlugin.java: migrate to v7 query() argument order, rename
  useProtocol() -> protocol(), switch wire format from Protocol.HTTP_VPACK to
  Protocol.HTTP2_JSON (the v7 default), and register a custom JacksonSerde
  with USE_LONG_FOR_INTS so query results preserve Long for integer values
  (matches the v6 VPACK behavior so the structure-tree column types stay
  stable for users)
- ArangoDBErrorUtils.java: walk the cause chain for UnknownHostException and
  also detect the v7 "Cannot contact any host" message, so the user-visible
  bad-host error stays the same as v6
- ArangoDBPluginTest.java: align fixture with the protocol/serde change and
  adjust two test-fixture values so the inserted documents match the
  collection schema cleanly under the v7 JSON serde (no production impact)

Validation:
- mvn dependency:tree on arangoDBPlugin: arangodb-java-driver:7.25.0,
  jackson-core:2.17.0; velocypack absent
- target/lib scan: zero jars contain META-INF jackson-core/pom.properties at
  version 2.11.3 (the shaded copy is gone)
- mvn -pl arangoDBPlugin -am test: 207/207 passing including all
  testcontainer-backed ArangoDB integration tests against arangodb:3.7.12
- live smoke test against arangodb:3.11.14: connect, read AQL, write AQL
  (writesExecuted/Ignored), and getCollections all succeed; numeric values
  return as Long as before

Refs: CVE-2025-52999, CVSS 8.7, jackson-core <2.15.0
@subrata71 subrata71 force-pushed the fix/cve-2025-52999-jackson-core branch from ef9e0a5 to a15e212 Compare May 10, 2026 05:07
@subrata71
Copy link
Copy Markdown
Collaborator Author

Update: Fixed PluginClassLoader / parent-classloader collision

The shadow EE PR (appsmithorg/appsmith-ee#9045) had all 60 Cypress shards failing at the same step (Setting up the tests) and the deploy preview pod was in CrashLoopBackOff. Server unit tests on this CE PR pass, but the same fix is needed here too because the runtime target/lib/ is generated identically.

Root cause (from the EE deploy-preview pod logs in ee9045 namespace)

PF4J fails to introspect ArangoDBPluginExecutor during Spring context init:

Caused by: java.lang.LinkageError: loader constraint violation:
loader org.pf4j.PluginClassLoader @... wants to load class
com.fasterxml.jackson.databind.ObjectMapper. A different class with
the same name was previously loaded by
org.springframework.boot.loader.launch.LaunchedClassLoader @...

The previous v6 driver pulled velocypack which shaded jackson under a relocated package, so the plugin's runtime lib/ had no com.fasterxml.jackson.* jars. The new v7 driver replaces velocypack with com.arangodb:jackson-serde-json, which depends on un-shaded jackson at compile scope. maven-dependency-plugin:copy-dependencies then ships those jars (plus Vert.x's transitive Netty 4.1.131) into target/lib/, colliding with the same versions already loaded by the Spring Boot parent classloader.

Fix

Mark the transitives that are also shipped by appsmith-server as <scope>provided</scope> in arangoDBPlugin/pom.xml, matching the pattern already used in graphqlPlugin, restApiPlugin, etc.:

  • com.fasterxml.jackson.core:{jackson-core, jackson-databind, jackson-annotations}
  • io.netty:netty-{buffer, codec, codec-dns, codec-http, codec-http2, codec-socks, common, handler, handler-proxy, resolver, resolver-dns, transport, transport-native-unix-common}

After the fix, target/lib/ no longer contains any com.fasterxml.jackson.* jars or io.netty:netty-* jars. The CVE remediation evidence is unchanged: zero shaded jackson-core 2.11.3 pom.properties in any lib/ jar.

Verification

  • mvn -pl appsmith-plugins/arangoDBPlugin -am test → 207/207 passing including testcontainer-backed integration tests.
  • mvn -pl appsmith-server -am package -DskipTests → BUILD SUCCESS (catches plugin-loader regressions).

@subrata71 subrata71 added the ok-to-test Required label for CI label May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Required label for CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant