Loading HuntDB...

GHSA-m49c-g9wr-hv6v

GitHub Security Advisory

jinjava has Sandbox Bypass via JavaType-Based Deserialization

✓ GitHub Reviewed CRITICAL Has CVE

Advisory Details

### Summary

jinjava’s current sandbox restrictions prevent direct access to dangerous methods such as `getClass()`, and block instantiation of Class objects. However, these protections can be bypassed.

By using mapper.getTypeFactory().constructFromCanonical(), it is possible to instruct the underlying ObjectMapper to deserialize attacker-controlled input into arbitrary classes. This enables the creation of semi-arbitrary class instances without directly invoking restricted methods or class literals.

As a result, an attacker can escape the sandbox and instantiate classes such as java.net.URL, opening up the ability to access local files and URLs(e.g., file:///etc/passwd). With further chaining, this primitive can potentially lead to remote code execution (RCE).

### Details

jinjava templates expose a built-in variable `____int3rpr3t3r____`, which provides direct access to the jinjavaInterpreter instance.
This variable was previously abused (see [Add interpreter to blacklist](https://github.com/HubSpot/jinjava/commit/1b9aaa4b420c58b4a301cf4b7d26207f1c8d1165)), and while protections were added to prevent call method from `JinjavaInterpreter` instances.
However, interacting with the properties of `JinjavaInterpreter` instances remains unrestricted.

From `____int3rpr3t3r____`, it is possible to traverse to the `config` field, which exposes an ObjectMapper. By invoking `readValue(String content, JavaType valueType)` on this ObjectMapper, an attacker can instantiate arbitrary classes specified via `JavaType`.

Although jinjava explicitly restricts dangerous classes such as `Class`, `ClassLoader`, and so on inside `JinjavaBeanELResolver`, the `JavaType` class itself is [not restricted](https://github.com/HubSpot/jinjava/blob/jinjava-2.8.0/src/main/java/com/hubspot/jinjava/el/ext/JinjavaBeanELResolver.java#L246-L262).

As a result, an attacker can leverage `JavaType` construction (`constructFromCanonical`) to instantiate semi-arbitrary classes without directly calling restricted methods.

This allows sandbox escape and the creation of powerful primitives. For example, instantiating `java.net.URL` enables reading arbitrary files, as shown in the following PoC (tested on Jinjava 2.8.0):

```
{% set mapper = ____int3rpr3t3r____.config.objectMapper %}
{{ mapper.enableDefaultTyping() }}
{% set file = mapper.readValue('"file:///etc/passwd"', mapper.getTypeFactory().constructFromCanonical('java.net.URL')) %}
{% set inputStream = file.openStream() %}
{% set bytes = inputStream.readAllBytes() %}
{% set stringType = mapper.getTypeFactory().constructFromCanonical('java.lang.String') %}
{% set content = mapper.convertValue(bytes, stringType) %}
{{ content }}
```

### Impact
Escape the Jinjava sandbox and instantiate a wide range of classes using JavaType.
This capability can be used to read arbitrary files, such as `/proc/self/environ`, and to perform full read SSRF by creating network-related objects.
In certain environments, depending on the available classes, this primitive can even lead to complete remote code execution.

Affected Packages

Maven com.hubspot.jinjava:jinjava
Affected versions: 0 (fixed in 2.8.1)

Related CVEs

Key Information

GHSA ID
GHSA-m49c-g9wr-hv6v
Published
September 17, 2025 7:56 PM
Last Modified
September 17, 2025 7:56 PM
CVSS Score
9.0 /10
Primary Ecosystem
Maven
Primary Package
com.hubspot.jinjava:jinjava
GitHub Reviewed
✓ Yes

Dataset

Last updated: September 18, 2025 6:29 AM

Data from GitHub Advisory Database. This information is provided for research and educational purposes.