Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
=== TinkerPop 3.7.7 (Release Date: NOT OFFICIALLY RELEASED YET)

* Disabled unsafe Java deserialization on the Gryo IO paths and added `GryoMapper.Builder.javaSerializationAllowed(boolean)` to control it.
* Hardened GraphSON 1.0 typed deserialization so that reading untrusted input can no longer construct arbitrary Java classes.
* Fixed `subgraph()` to throw a descriptive error identifying the required `Edge` input instead of an internal `ClassCastException` when the traversal produces a non-edge value.
* Fixed `where(P)` to throw a descriptive error identifying the required String scope key (and suggesting `is(P)` for value comparisons) instead of an internal `ClassCastException` when given a non-String predicate value.
* Fixed `PeerPressure.property_name` in `gremlin-python` incorrectly mapping to the `pageRank` property name token.
Expand Down
5 changes: 3 additions & 2 deletions THREAT_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ Knobs that change which security properties hold (Gremlin Server, `gremlin-serve
`gremlin-server-secure.yaml`. The docs are explicit that TinkerPop offers no complete out-of-the-box
protection against nefarious scripts. *(documented — `gremlin-applications.asciidoc` "Protecting Script
Execution", the two sample configs)*
- **Enabled serializers** — wire set is GraphSON 3.0 + GraphBinary. Gryo is IO-format-only, not on the wire,
- **Enabled serializers** — the default wire set is GraphSON 3.0 + GraphBinary. The typed GraphSON 1.0 serializer (`vnd.gremlin-v1.0+json`) is also shippable and constrains its `@class` default typing to an allow-list (§8). Gryo is IO-format-only, not on the wire,
and defaults to a locked registration allow-list (`registrationRequired=true`). Disabling that lock removes
the untrusted-input protection (§9). *(documented — sample configs, `gremlin-applications.asciidoc`
"Serialization")*
Expand Down Expand Up @@ -341,7 +341,8 @@ Per-surface trust table:
IO paths build** (`registrationRequired=true` plus `javaSerializationAllowed=false`, i.e. `io()`, `GryoReader`,
`GryoWriter`, `GryoIo`, and the Hadoop Gryo input/output formats) reading attacker bytes do not reach native Java
deserialization
(`ObjectInputStream.readObject()`). Because `inject()` and value arguments let a request carry any
(`ObjectInputStream.readObject()`), and do not instantiate an arbitrary class named in the document: GraphSON 1.0
embedded types constrain Jackson default typing to a validated type allow-list. Because `inject()` and value arguments let a request carry any
supported type, a bug in a **registered** type's (de)serializer that crashes/OOMs the reader is also
in-model, on **both** the server (request) and the GLV (response) side. The GraphML reader disables
external entities and DTDs by default (XXE-safe). *Violation symptom:* deserialization gadget / RCE / XXE,
Expand Down
9 changes: 8 additions & 1 deletion docs/src/dev/io/graphson.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ Version 1.0 of GraphSON was released with TinkerPop 3.0.0. It is referred to by
When types are embedded, GraphSON uses the standard
link:https://github.com/FasterXML/jackson-databind[Jackson] type embedding approach that writes the full Java class
name into a "@class" field in the JSON. While this approach isn't especially language agnostic it does at least give
some hint as to what the expected type is.
some hint as to what the expected type is. On read, that class name is constrained to a validated allow-list so that
an untrusted document cannot name an arbitrary class for construction. A class outside the allowed set is refused.
The allow-list permits classes in the `java.lang`, `java.util`, `java.math`, `java.time`, `java.sql` and
`org.apache.tinkerpop` packages (and their subpackages) plus array types, and by exact name a few safe value types
in otherwise-excluded packages (`java.net.InetAddress`, `java.net.URI`); the rest of `java.net` and `java.nio` is
excluded, and a parameterized type id or a `java.lang.Class` value is refused. A provider or application reading
trusted input can add its own package with `GraphSONMapper.Builder.addAllowedTypeIdPrefix(String...)`, for example
`addAllowedTypeIdPrefix("com.example.")`.

This section focuses on non-embedded types and their formats as there was little usage of embedded types in generalized
object serialization use cases. The format was simply too cumbersome to parse of non-Jackson enabled libraries and the
Expand Down
35 changes: 35 additions & 0 deletions docs/src/upgrade/release-3.7.x.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,41 @@ GryoIo.build().graph(graph).onMapper(m -> ((GryoMapper.Builder) m).javaSerializa

See: link:https://issues.apache.org/jira/browse/TINKERPOP-3278[TINKERPOP-3278]

==== GraphSON 1.0 Restricts Embedded-Type Deserialization

GraphSON 1.0 with embedded types (`TypeInfo.PARTIAL_TYPES`) reconstructs a value from the Java class named in a
`@class` property using Jackson default typing. That mechanism previously resolved any class named in the document,
which is an unsafe-deserialization vector when reading untrusted input. Default typing is now constrained by a
`PolymorphicTypeValidator` that allows classes in the value packages GraphSON 1.0 legitimately round-trips
(`java.lang`, `java.util`, `java.math`, `java.time`, `java.sql`, `org.apache.tinkerpop`, and their subpackages) plus
array types, and by exact name a few safe value types in otherwise-excluded packages (`java.net.InetAddress`,
`java.net.URI`). The rest of `java.net` and `java.nio` is excluded, and a parameterized type id or a
`java.lang.Class` value is refused. Standard scalar, collection and array values are unaffected. Some value types
are written by V1 as a concrete subtype Jackson cannot reconstruct (`java.nio.ByteBuffer`); this was never
round-trippable in V1 and remains refused on read.

A document whose `@class` names a type outside that set is now refused rather than instantiated:

[source,text]
----
Could not resolve type id ...: Configured `PolymorphicTypeValidator` ... denied resolution
----

Applications that deliberately read a custom or provider value type through GraphSON 1.0 embedded types (for
example a type registered via an `IoRegistry`) can re-enable it, for trusted input, by trusting its package on the
mapper:

[source,java]
----
GraphSONMapper.build().version(GraphSONVersion.V1_0).typeInfo(TypeInfo.PARTIAL_TYPES)
.addAllowedTypeIdPrefix("com.example.").create();
----

GraphSON 2.0 and 3.0 were never affected: they resolve types through a fixed registry rather than by arbitrary
class name.

See: link:https://issues.apache.org/jira/browse/TINKERPOP-3279[TINKERPOP-3279]

==== conjoin() Step Null Handling

The `conjoin()` step previously returned `null` when elements in the incoming list are `null`. This behavior has
Expand Down
Loading
Loading