You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2026/07/29 21:09:12 UTC
(tinkerpop) 02/02: Bump jackson-databind (shaded) to 2.18.9
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch 3.7-dependencies
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 5e6ac794a590f2ca5246f25b58cba2ca58662017
Author: Cole Greer <co...@colegreer.ca>
AuthorDate: Wed Jul 29 14:07:07 2026 -0700
Bump jackson-databind (shaded) to 2.18.9
Upgrades the jackson-databind dependency pinned in gremlin-shaded from
2.15.2 to 2.18.9 to address multiple CVEs accumulated across the 2.15.x-
2.18.x line (deserialization gadgets, DoS, SSRF-via-DNS-lookup, etc.).
Required compile fixes for removed/changed Jackson APIs:
- GraphSONSerializerProvider: implement the new abstract
withCaches(CacheProvider) method added in jackson-databind 2.16
(databind#2502). TinkerPop never configures a custom CacheProvider,
so this is effectively inert at runtime, but is required to satisfy
the abstract contract; implementation mirrors Jackson's own
DefaultSerializerProvider.Impl pattern.
- GraphSONTypeDeserializer: replace the removed
DeserializationContext.mappingException(String) (deprecated since
2.9, physically removed by 2.18) with the documented replacement
reportInputMismatch(JavaType, String).
- GraphSONStreamConstraintsTest: update three assertions to match
Jackson's reworded StreamConstraintsException messages (behavior
unchanged, only message text changed upstream).
Also required bumping maven-shade-plugin 3.4.1 -> 3.6.2 in the root
pom, since 3.4.1's bundled ASM version cannot parse the Java 21
multi-release JAR classes shipped in jackson-core 2.18.9, causing the
gremlin-shaded shade step to fail. No relocation-logic or default-
behavior changes exist between 3.4.1 and 3.6.2 for TinkerPop's use case
(verified against upstream release notes).
Breaking change: jackson-databind 2.18.9 hardens InetAddress
deserialization to reject hostname strings (only literal IP addresses
are accepted), closing a DNS-lookup-on-untrusted-input vector
(jackson-databind#6058, related to CVE-2026-54514 for the sibling
InetSocketAddress type). This has no configurable opt-out upstream.
Rather than reintroducing hostname resolution via a custom
deserializer, this change adopts Jackson's restriction as-is, since
Gremlin Server's threat model should not assume GraphSON input is
trusted enough to justify DNS lookups during deserialization. Updated
InetAddress test fixtures/model data to use literal IP addresses
instead of hostnames, and documented the break in
docs/src/upgrade/release-3.7.x.asciidoc and CHANGELOG.asciidoc.
Deferred to a follow-up: Jackson dependencies pulled in transitively
via hadoop-gremlin, spark-gremlin, and sparql-gremlin (Hadoop/Spark/
Jena) still resolve to their own older Jackson versions independently
and were not addressed here.
Assisted-by: Kiro:claude-sonnet-5 [code] [execute_bash] [fs_write] [grep]
---
CHANGELOG.asciidoc | 1 +
docs/src/dev/io/graphson.asciidoc | 4 ++--
docs/src/upgrade/release-3.7.x.asciidoc | 12 ++++++++++++
.../structure/io/graphson/GraphSONSerializerProvider.java | 11 +++++++++++
.../structure/io/graphson/GraphSONTypeDeserializer.java | 4 ++--
.../structure/io/graphson/GraphSONStreamConstraintsTest.java | 12 ++++++------
gremlin-shaded/pom.xml | 2 +-
.../org/apache/tinkerpop/gremlin/structure/io/Model.java | 2 +-
.../tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java | 2 +-
.../gremlin/structure/io/graphson/inetaddress-v2.json | 2 +-
.../gremlin/structure/io/graphson/inetaddress-v3.json | 2 +-
pom.xml | 2 +-
12 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index b1824b0b80..fdd3ad8631 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -36,6 +36,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Allowed float literals without a leading digit (e.g. `.5`, `.5f`, `.5d`) in the Gremlin grammar to better match Groovy.
* Fixed conjoin has incorrect null handling.
* Bump Netty to 4.1.136.
+* Bumped `jackson-databind` to 2.18.9. `InetAddress` values in GraphSON must now be literal IP addresses as hostnames are no longer resolved during deserialization. *(breaking)*
* Removed the Mono dependency from the `gremlin-dotnet` build/release process, using `dotnet pack`/`dotnet nuget push` instead of `mono nuget.exe`.
* Expanded `gremlin-python` CI matrix to test against Python 3.9, 3.10, 3.11, 3.12, and 3.13.
* Add Node 26 support for `gremlin-javascript` and `gremlint`.
diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc
index 5b500c0118..a4dd40a1a4 100644
--- a/docs/src/dev/io/graphson.asciidoc
+++ b/docs/src/dev/io/graphson.asciidoc
@@ -3369,7 +3369,7 @@ The following example is a `Duration` of five days.
----
{
"@type" : "gx:InetAddress",
- "@value" : "localhost"
+ "@value" : "127.0.0.1"
}
----
@@ -5738,7 +5738,7 @@ The following example is a `Duration` of five days.
----
{
"@type" : "gx:InetAddress",
- "@value" : "localhost"
+ "@value" : "127.0.0.1"
}
----
diff --git a/docs/src/upgrade/release-3.7.x.asciidoc b/docs/src/upgrade/release-3.7.x.asciidoc
index 4fa1a36cc7..4fc6ccc3d4 100644
--- a/docs/src/upgrade/release-3.7.x.asciidoc
+++ b/docs/src/upgrade/release-3.7.x.asciidoc
@@ -119,6 +119,18 @@ removed in 4.0.0. This deprecation applies across all Gremlin Language Variants.
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3042[TINKERPOP-3042]
+==== InetAddress GraphSON Deserialization No Longer Resolves Hostnames
+
+TinkerPop's Jackson dependency was upgraded to jackson-databind 2.18.9 to address a number of CVEs. As part of that
+upgrade, Jackson changed how it deserializes `java.net.InetAddress` values from GraphSON, it will no longer perform a
+DNS lookup to resolve a hostname string (e.g. `"localhost"`, `"example.com"`) into an `InetAddress`. Only literal IPv4
+or IPv6 address strings (e.g. `"127.0.0.1"`, `"::1"`) are now accepted, anything else fails deserialization with an
+error such as `Not a valid IP address string literal`.
+
+Applications that store or transmit `InetAddress` values via GraphSON (as a vertex/edge property, or as a bound
+Gremlin parameter) must use literal IP address strings going forward. Existing serialized data containing hostname
+strings will fail to deserialize after upgrading and will need to be migrated to literal IP addresses.
+
== TinkerPop 3.7.6
*Release Date: April 1, 2026*
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
index fc5810bdfd..8603116a28 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.structure.io.graphson;
import org.apache.tinkerpop.shaded.jackson.databind.JsonSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.SerializationConfig;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
+import org.apache.tinkerpop.shaded.jackson.databind.cfg.CacheProvider;
import org.apache.tinkerpop.shaded.jackson.databind.ser.DefaultSerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.ser.SerializerFactory;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.ToStringSerializer;
@@ -55,6 +56,11 @@ final class GraphSONSerializerProvider extends DefaultSerializerProvider {
this.unknownTypeSerializer = unknownTypeSerializer;
}
+ protected GraphSONSerializerProvider(final GraphSONSerializerProvider src, final CacheProvider cacheProvider) {
+ super(src, cacheProvider);
+ this.unknownTypeSerializer = src.unknownTypeSerializer;
+ }
+
@Override
public JsonSerializer<Object> getUnknownTypeSerializer(final Class<?> aClass) {
return unknownTypeSerializer;
@@ -69,4 +75,9 @@ final class GraphSONSerializerProvider extends DefaultSerializerProvider {
// that has a GraphSONVersion.
return new GraphSONSerializerProvider(this, config, jsf, unknownTypeSerializer);
}
+
+ @Override
+ public GraphSONSerializerProvider withCaches(final CacheProvider cacheProvider) {
+ return new GraphSONSerializerProvider(this, cacheProvider);
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
index 5fbf839b15..4c82932118 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
@@ -184,14 +184,14 @@ public class GraphSONTypeDeserializer extends TypeDeserializerBase {
// detected the type pattern entirely but the Map contained other properties
// For now we error out because we assume that pattern is *only* reserved to
// typed values.
- throw deserializationContext.mappingException("Detected the type pattern in the JSON payload " +
+ deserializationContext.reportInputMismatch(baseType, "Detected the type pattern in the JSON payload " +
"but the map containing the types and values contains other fields. This is not " +
"allowed by the deserializer.");
}
}
}
} catch (Exception e) {
- throw deserializationContext.mappingException("Could not deserialize the JSON value as required. Nested exception: " + e.toString());
+ deserializationContext.reportInputMismatch(baseType, "Could not deserialize the JSON value as required. Nested exception: " + e.toString());
}
// Type pattern wasn't detected, however,
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONStreamConstraintsTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONStreamConstraintsTest.java
index 683776e74a..4f96f14f1f 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONStreamConstraintsTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONStreamConstraintsTest.java
@@ -48,8 +48,8 @@ public class GraphSONStreamConstraintsTest extends AbstractGraphSONTest{
serializeDeserializeAuto(mapper, serializedData);
});
assertTrue("Expected StreamConstraintsException for exceeding max number length, found: "+exception.getMessage(),
- exception.getMessage().contains("org.apache.tinkerpop.shaded.jackson.core.exc.StreamConstraintsException: Number length")
- && exception.getMessage().contains("exceeds the maximum length (2)"));
+ exception.getMessage().contains("org.apache.tinkerpop.shaded.jackson.core.exc.StreamConstraintsException: Number value length")
+ && exception.getMessage().contains("exceeds the maximum allowed (2, from `StreamReadConstraints.getMaxNumberLength()`)"));
}
@Test
@@ -66,8 +66,8 @@ public class GraphSONStreamConstraintsTest extends AbstractGraphSONTest{
serializeDeserializeAuto(mapper, serializedData);
});
assertTrue("Expected StreamConstraintsException for exceeding max String length, found: "+exception.getMessage(),
- exception.getMessage().contains("String length")
- && exception.getMessage().contains("exceeds the maximum length (20)"));
+ exception.getMessage().contains("String value length")
+ && exception.getMessage().contains("exceeds the maximum allowed (20, from `StreamReadConstraints.getMaxStringLength()`)"));
}
@Test
@@ -87,7 +87,7 @@ public class GraphSONStreamConstraintsTest extends AbstractGraphSONTest{
serializeDeserializeAuto(mapper, serializedData);
});
assertTrue("Expected StreamConstraintsException for exceeding max nesting depth, found: "+exception.getMessage(),
- exception.getMessage().contains("org.apache.tinkerpop.shaded.jackson.core.exc.StreamConstraintsException: Depth")
- && exception.getMessage().contains("exceeds the maximum allowed nesting depth (1)"));
+ exception.getMessage().contains("org.apache.tinkerpop.shaded.jackson.core.exc.StreamConstraintsException: Document nesting depth")
+ && exception.getMessage().contains("exceeds the maximum allowed (1, from `StreamReadConstraints.getMaxNestingDepth()`)"));
}
}
diff --git a/gremlin-shaded/pom.xml b/gremlin-shaded/pom.xml
index d87bfb1f55..e38771295b 100644
--- a/gremlin-shaded/pom.xml
+++ b/gremlin-shaded/pom.xml
@@ -48,7 +48,7 @@ limitations under the License.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
- <version>2.15.2</version>
+ <version>2.18.9</version>
<optional>true</optional>
</dependency>
</dependencies>
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/Model.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
index 7a81678a81..d4788bd5aa 100644
--- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
@@ -217,7 +217,7 @@ public class Model {
addExtendedEntry("x".charAt(0), "Char", "");
addExtendedEntry(Duration.ofDays(5), "Duration","The following example is a `Duration` of five days.");
try {
- addEntry("Extended", InetAddress.getByName("localhost"), "InetAddress", "");
+ addEntry("Extended", InetAddress.getByName("127.0.0.1"), "InetAddress", "");
} catch (Exception ex) {
throw new RuntimeException(ex);
}
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
index 2b3fdaa984..4ba4cede70 100644
--- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
@@ -205,7 +205,7 @@ public abstract class AbstractRoundTripTest {
new Object[] {"Traverser", new DefaultRemoteTraverser<>("marko", 100), null},
new Object[] {"Class", Bytecode.class, null},
new Object[] {"ByteBuffer", ByteBuffer.wrap(new byte[]{ 1, 2, 3 }), null},
- new Object[] {"InetAddressV4", InetAddress.getByName("localhost"), null},
+ new Object[] {"InetAddressV4", InetAddress.getByName("127.0.0.1"), null},
new Object[] {"InetAddressV6", InetAddress.getByName("::1"), null},
new Object[] {"Lambda0", Lambda.supplier("return 1"), null},
new Object[] {"Lambda1", Lambda.consumer("it"), null},
diff --git a/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v2.json b/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v2.json
index fba98c0246..64196028c7 100644
--- a/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v2.json
+++ b/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v2.json
@@ -1,4 +1,4 @@
{
"@type" : "gx:InetAddress",
- "@value" : "localhost"
+ "@value" : "127.0.0.1"
}
\ No newline at end of file
diff --git a/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v3.json b/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v3.json
index fba98c0246..64196028c7 100644
--- a/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v3.json
+++ b/gremlin-util/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/inetaddress-v3.json
@@ -1,4 +1,4 @@
{
"@type" : "gx:InetAddress",
- "@value" : "localhost"
+ "@value" : "127.0.0.1"
}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 434cfcd2aa..2a610af3a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -716,7 +716,7 @@ limitations under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
- <version>3.4.1</version>
+ <version>3.6.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>