GitHub Security Advisory: GHSA-mggx-p7jf-jgw4
Package: org.jdbi:jdbi3-freemarker (MAVEN)
Severity: HIGH (CVSS 0.0)
CWE: CWE-94: Improper Control of Generation of Code ('Code Injection'), CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine
Vulnerable versions: <= 3.52.1
Patched in: 3.53.0

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:
```java
// 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");
}
```

```java
// 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()`:
```java
// 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-freemarker`and