VYPR
Critical severityNVD Advisory· Published Feb 4, 2026· Updated Feb 5, 2026

JinJava Bypass through ForTag leads to Arbitrary Java Execution

CVE-2026-25526

Description

JinJava is a Java-based template engine based on django template syntax, adapted to render jinja templates. Prior to versions 2.7.6 and 2.8.3, JinJava is vulnerable to arbitrary Java execution via bypass through ForTag. This allows arbitrary Java class instantiation and file access bypassing built-in sandbox restrictions. This issue has been patched in versions 2.7.6 and 2.8.3.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

JinJava sandbox bypass in ForTag allows arbitrary Java class instantiation and file access via template rendering.

Vulnerability

Description JinJava, a Java-based template engine for Jinja, prior to versions 2.7.6 and 2.8.3, contains a sandbox bypass vulnerability in the ForTag class. The issue arises because ForTag does not enforce restrictions from JinjavaBeanELResolver when iterating over object properties using Java's Introspector and invoking getter methods via PropertyDescriptor.getReadMethod(). This allows an attacker to bypass the built-in sandbox that is intended to restrict access to sensitive classes and methods [1][3].

Exploitation

An attacker with the ability to create or edit Jinja templates can exploit this by crafting a ForTag loop that accesses properties of objects in the template context. By using ObjectMapper instantiation, the attacker can enable default typing to bypass the type allowlist, instantiate arbitrary Java classes, and read files from the server filesystem (e.g., /etc/passwd). No authentication is required if the template engine is exposed to untrusted user input [3].

Impact

Successful exploitation allows arbitrary Java class instantiation and file access, potentially leading to remote code execution. This is a critical severity issue (CVSS 9.8) that compromises the confidentiality, integrity, and availability of the affected system [3].

Mitigation

The vulnerability has been patched in JinJava versions 2.7.6 and 2.8.3. Users should upgrade immediately. The fix adds security checks to ForTag.renderForCollection() to enforce property access restrictions and validates class types before introspection [1][3].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.hubspot.jinjava:jinjavaMaven
>= 2.8.0, < 2.8.32.8.3
com.hubspot.jinjava:jinjavaMaven
< 2.7.62.7.6

Affected products

2
  • JinJava/JinJavallm-create
    Range: < 2.7.6, < 2.8.3
  • HubSpot/jinjavav5
    Range: < 2.7.6

Patches

2
c7328dce6030

Merge commit from fork

https://github.com/HubSpot/jinjavaJack SmithFeb 2, 2026via ghsa
1 file changed · +15 16
  • src/test/java/com/hubspot/jinjava/el/ext/JinjavaBeanELResolverTest.java+15 16 modified
    @@ -10,6 +10,7 @@
     import com.hubspot.jinjava.JinjavaConfig;
     import com.hubspot.jinjava.el.JinjavaELContext;
     import com.hubspot.jinjava.interpret.JinjavaInterpreter;
    +import java.util.ArrayList;
     import java.util.List;
     import javax.el.ELContext;
     import javax.el.MethodNotFoundException;
    @@ -189,25 +190,21 @@ public void itDoesNotAllowAccessingPropertiesOfInterpreter() {
     
       @Test
       public void itDoesNotGettingFromObjectMapper() {
    -    try (
    -      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    -        .closeablePushCurrent(interpreter)
    -        .get()
    -    ) {
    +    JinjavaInterpreter.pushCurrent(interpreter);
    +    try {
           assertThat(
             jinjavaBeanELResolver.getValue(elContext, new ObjectMapper(), "dateFormat")
           )
             .isNull();
    +    } finally {
    +      JinjavaInterpreter.popCurrent();
         }
       }
     
       @Test
       public void itDoesNotAllowInvokingFromObjectMapper() throws NoSuchMethodException {
    -    try (
    -      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    -        .closeablePushCurrent(interpreter)
    -        .get()
    -    ) {
    +    JinjavaInterpreter.pushCurrent(interpreter);
    +    try {
           ObjectMapper objectMapper = new ObjectMapper();
           assertThatThrownBy(() ->
               jinjavaBeanELResolver.invoke(
    @@ -219,17 +216,17 @@ public void itDoesNotAllowInvokingFromObjectMapper() throws NoSuchMethodExceptio
               )
             )
             .isInstanceOf(MethodNotFoundException.class);
    +    } finally {
    +      JinjavaInterpreter.popCurrent();
         }
       }
     
       @Test
       public void itDoesNotAllowInvokingFromMethod() throws NoSuchMethodException {
    -    try (
    -      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    -        .closeablePushCurrent(interpreter)
    -        .get()
    -    ) {
    -      List<String> list = List.of("foo");
    +    JinjavaInterpreter.pushCurrent(interpreter);
    +    try {
    +      List<String> list = new ArrayList<>();
    +      list.add("foo");
           assertThatThrownBy(() ->
               jinjavaBeanELResolver.invoke(
                 elContext,
    @@ -240,6 +237,8 @@ public void itDoesNotAllowInvokingFromMethod() throws NoSuchMethodException {
               )
             )
             .isInstanceOf(MethodNotFoundException.class);
    +    } finally {
    +      JinjavaInterpreter.popCurrent();
         }
       }
     }
    
3d02e504d8bb

Merge commit from fork

https://github.com/HubSpot/jinjavaJack SmithFeb 2, 2026via ghsa
5 files changed · +92 3
  • CHANGES.md+14 0 modified
    @@ -1,9 +1,23 @@
     # Jinjava Releases #
    +### 2025-01-30 Version 2.8.3 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.3/jar)) ###
    +* Disallow accessing properties on restricted classes while rendering through ForTag
    +* Upgrade jackson to version 2.20
    +* [Add performance optimization to chained filters](https://github.com/HubSpot/jinjava/pull/1274)
    +
    +### 2025-01-30 Version 2.7.6 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.7.6/jar)) ###
    +* Disallow accessing properties on restricted classes while rendering through ForTag
    +* Upgrade jackson to version 2.20
    +
     ### 2025-10-22 Version 2.8.2 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.2/jar)) ###
     * [Fix helper token escape handling and unescaping when unquoting strings](https://github.com/HubSpot/jinjava/pull/1263)
    +
    +### 2025-09-30 Version 2.7.5 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.7.5/jar)) ###
    +* Disallow accessing properties on restricted classes while rendering
    +
     ### 2025-09-16 Version 2.8.1 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.1/jar)) ###
     * Disallow accessing properties on restricted classes while rendering
     * [Make stack operations use AutoCloseable for safer usage with try-with-resources](https://github.com/HubSpot/jinjava/pull/1250)
    +
     ### 2025-05-05 Version 2.8.0 ([Maven Central](https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.0/jar)) ###
     * [Target Java 17](https://github.com/HubSpot/jinjava/pull/1238)
     * [Implement PyMap#get with optional default](https://github.com/HubSpot/jinjava/pull/1233)
    
  • src/main/java/com/hubspot/jinjava/el/ext/JinjavaBeanELResolver.java+10 2 modified
    @@ -1,5 +1,6 @@
     package com.hubspot.jinjava.el.ext;
     
    +import com.fasterxml.jackson.databind.ObjectMapper;
     import com.google.common.base.CaseFormat;
     import com.google.common.collect.ImmutableSet;
     import com.hubspot.jinjava.interpret.DeferredValueException;
    @@ -36,6 +37,7 @@ public class JinjavaBeanELResolver extends BeanELResolver {
         .add("notify")
         .add("notifyAll")
         .add("wait")
    +    .add("readValueAs")
         .build();
     
       private static final Set<String> DEFERRED_EXECUTION_RESTRICTED_METHODS = ImmutableSet
    @@ -59,6 +61,10 @@ public class JinjavaBeanELResolver extends BeanELResolver {
         .add("set")
         .add("merge")
         .build();
    +  private static final String JAVA_LANG_REFLECT_PACKAGE =
    +    Method.class.getPackage().getName(); // java.lang.reflect
    +  private static final String JACKSON_DATABIND_PACKAGE =
    +    ObjectMapper.class.getPackage().getName(); // com.fasterxml.jackson.databind
     
       /**
        * Creates a new read/write {@link JinjavaBeanELResolver}.
    @@ -251,9 +257,11 @@ protected boolean isRestrictedClass(Object o) {
           return false;
         }
     
    +    Package oPackage = o.getClass().getPackage();
         return (
    -      (o.getClass().getPackage() != null &&
    -        o.getClass().getPackage().getName().startsWith("java.lang.reflect")) ||
    +      (oPackage != null &&
    +        (oPackage.getName().startsWith(JAVA_LANG_REFLECT_PACKAGE) ||
    +          oPackage.getName().startsWith(JACKSON_DATABIND_PACKAGE))) ||
           o instanceof Class ||
           o instanceof ClassLoader ||
           o instanceof Thread ||
    
  • src/main/java/com/hubspot/jinjava/lib/tag/ForTag.java+1 1 modified
    @@ -247,7 +247,7 @@ public String renderForCollection(
                       if (loopVar.equals(valProp.getName())) {
                         interpreter
                           .getContext()
    -                      .put(loopVar, valProp.getReadMethod().invoke(val));
    +                      .put(loopVar, interpreter.resolveProperty(val, valProp.getName()));
                         break;
                       }
                     }
    
  • src/test/java/com/hubspot/jinjava/el/ext/JinjavaBeanELResolverTest.java+58 0 modified
    @@ -5,11 +5,13 @@
     import static org.mockito.Mockito.mock;
     import static org.mockito.Mockito.when;
     
    +import com.fasterxml.jackson.databind.ObjectMapper;
     import com.google.common.collect.ImmutableSet;
     import com.hubspot.jinjava.JinjavaConfig;
     import com.hubspot.jinjava.el.JinjavaELContext;
     import com.hubspot.jinjava.interpret.AutoCloseableSupplier;
     import com.hubspot.jinjava.interpret.JinjavaInterpreter;
    +import java.util.List;
     import javax.el.ELContext;
     import javax.el.MethodNotFoundException;
     import javax.el.PropertyNotFoundException;
    @@ -186,4 +188,60 @@ public void itDoesNotAllowAccessingPropertiesOfInterpreter() {
             .isNull();
         }
       }
    +
    +  @Test
    +  public void itDoesNotGettingFromObjectMapper() {
    +    try (
    +      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    +        .closeablePushCurrent(interpreter)
    +        .get()
    +    ) {
    +      assertThat(
    +        jinjavaBeanELResolver.getValue(elContext, new ObjectMapper(), "dateFormat")
    +      )
    +        .isNull();
    +    }
    +  }
    +
    +  @Test
    +  public void itDoesNotAllowInvokingFromObjectMapper() throws NoSuchMethodException {
    +    try (
    +      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    +        .closeablePushCurrent(interpreter)
    +        .get()
    +    ) {
    +      ObjectMapper objectMapper = new ObjectMapper();
    +      assertThatThrownBy(() ->
    +          jinjavaBeanELResolver.invoke(
    +            elContext,
    +            objectMapper,
    +            "getDateFormat",
    +            new Class[] {},
    +            new Object[] {}
    +          )
    +        )
    +        .isInstanceOf(MethodNotFoundException.class);
    +    }
    +  }
    +
    +  @Test
    +  public void itDoesNotAllowInvokingFromMethod() throws NoSuchMethodException {
    +    try (
    +      AutoCloseableSupplier.AutoCloseableImpl<JinjavaInterpreter> c = JinjavaInterpreter
    +        .closeablePushCurrent(interpreter)
    +        .get()
    +    ) {
    +      List<String> list = List.of("foo");
    +      assertThatThrownBy(() ->
    +          jinjavaBeanELResolver.invoke(
    +            elContext,
    +            list.getClass().getMethod("get", int.class),
    +            "invoke",
    +            new Class[] { Object.class, Object[].class },
    +            new Object[] { list, 0 }
    +          )
    +        )
    +        .isInstanceOf(MethodNotFoundException.class);
    +    }
    +  }
     }
    
  • src/test/java/com/hubspot/jinjava/lib/tag/ForTagTest.java+9 0 modified
    @@ -406,6 +406,15 @@ public void forLoopTupleWithNullValues() {
         assertThat(result).isEqualTo(" -1  -1  null  null  null ");
       }
     
    +  @Test
    +  public void itUsesJinjavaRestrictedResolverOnReadingLoopVars() {
    +    String template =
    +      """
    +      {% for _, config, class in ____int3rpr3t3r____ %}{{ class }}{% endfor %}""";
    +    String result = interpreter.render(template);
    +    assertThat(result).isEqualTo("");
    +  }
    +
       public static boolean inForLoop() {
         JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent();
         return interpreter.getContext().isInForLoop();
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.