CVE-2026-3960 Overview
A critical remote code execution vulnerability exists in the unauthenticated REST API endpoint /99/ImportSQLTable in H2O-3 version 3.46.0.9 and prior. The vulnerability arises due to insufficient security controls in the parameter blacklist mechanism, which only targets MySQL JDBC driver-specific dangerous parameters. An attacker can bypass these controls by switching the JDBC URL protocol to jdbc:postgresql: and exploiting PostgreSQL JDBC driver-specific parameters such as socketFactory and socketFactoryArg. This allows unauthenticated attackers to execute arbitrary code on the H2O-3 server with the privileges of the H2O-3 process.
Critical Impact
Unauthenticated remote code execution via JDBC protocol bypass allows attackers to gain complete control of the H2O-3 server and execute arbitrary commands with server process privileges.
Affected Products
- H2O-3 version 3.46.0.9 and prior
- H2O-3 deployments with exposed /99/ImportSQLTable REST API endpoint
- Systems using H2O-3 with network-accessible API interfaces
Discovery Timeline
- 2026-04-23 - CVE CVE-2026-3960 published to NVD
- 2026-04-23 - Last updated in NVD database
Technical Details for CVE-2026-3960
Vulnerability Analysis
This vulnerability is classified as Code Injection (CWE-94) and affects the SQL import functionality in H2O-3's REST API. The core issue stems from an incomplete parameter blacklist implementation in the SQLManager.java component. While the developers implemented security controls to block dangerous MySQL JDBC parameters like autoDeserialize and queryInterceptors, they failed to account for similar dangerous parameters in the PostgreSQL JDBC driver.
The unauthenticated nature of the /99/ImportSQLTable endpoint significantly increases the risk, as attackers do not need any credentials to exploit this vulnerability. By crafting a malicious JDBC connection string using the PostgreSQL protocol scheme, an attacker can specify arbitrary Java classes via the socketFactory parameter, leading to arbitrary code execution within the context of the H2O-3 process.
Root Cause
The root cause is an incomplete security blacklist in the JDBC parameter validation logic. The original implementation focused exclusively on MySQL-specific dangerous parameters while overlooking equivalent attack vectors in other supported JDBC drivers, particularly PostgreSQL. This represents a classic case of insufficient input validation where security controls were not comprehensively applied across all supported protocols.
Attack Vector
The attack leverages the network-accessible REST API endpoint /99/ImportSQLTable. An attacker constructs a malicious JDBC URL using the jdbc:postgresql: protocol scheme and includes parameters such as socketFactory and socketFactoryArg to specify a malicious Java class that will be instantiated during the connection attempt. Since the endpoint requires no authentication, any network-accessible H2O-3 instance is vulnerable to exploitation.
The following patch demonstrates how the vulnerability was addressed by expanding the parameter blacklist to include PostgreSQL-specific dangerous parameters:
private static final Pattern JDBC_PARAMETERS_REGEX_PATTERN = Pattern.compile("(?i)([a-z0-9_]+)\\s*=\\s*");
private static final List<String> DEFAULT_JDBC_DISALLOWED_PARAMETERS = Stream.of(
- "autoDeserialize", "queryInterceptors", "allowLoadLocalInfile", "allowMultiQueries", //mysql
- "allowLoadLocalInfileInPath", "allowUrlInLocalInfile", "allowPublicKeyRetrieval", //mysql
+ "autoDeserialize", "queryInterceptors", "allowLoadLocalInfile", "allowMultiQueries", //mysql
+ "allowLoadLocalInfileInPath", "allowUrlInLocalInfile", "allowPublicKeyRetrieval", //mysql
+ "statementInterceptors", //mysql
+ "socketFactory", "socketFactoryArg", "sslfactory", "sslfactoryarg", //postgresql
+ "loggerLevel", "loggerFile", //postgresql -- not dangerous but user should not have a reason to use them
"init", "script", "shutdown" //h2
).map(String::toLowerCase).collect(Collectors.toList());
private static AtomicLong NEXT_TABLE_NUM = new AtomicLong(0);
Source: GitHub Commit Update
Detection Methods for CVE-2026-3960
Indicators of Compromise
- HTTP requests to the /99/ImportSQLTable endpoint containing jdbc:postgresql: protocol strings
- JDBC connection attempts with suspicious parameters such as socketFactory, socketFactoryArg, sslfactory, or sslfactoryarg
- Unexpected process spawning or network connections originating from the H2O-3 process
Detection Strategies
- Implement web application firewall (WAF) rules to inspect requests to /99/ImportSQLTable for PostgreSQL protocol strings with dangerous parameters
- Monitor H2O-3 application logs for unusual SQL import requests, particularly those using non-MySQL JDBC protocols
- Deploy network intrusion detection signatures to identify exploitation attempts targeting this endpoint
- Enable endpoint detection and response (EDR) monitoring for anomalous behavior from H2O-3 processes
Monitoring Recommendations
- Configure alerting for any access to the /99/ImportSQLTable endpoint from untrusted network sources
- Monitor for child process creation from H2O-3 Java processes that may indicate code execution
- Review JDBC connection strings in application logs for unexpected protocol schemes or parameters
- Implement baseline monitoring for H2O-3 process behavior to detect deviations indicating exploitation
How to Mitigate CVE-2026-3960
Immediate Actions Required
- Upgrade H2O-3 to version 3.46.0.10 or later immediately
- Restrict network access to the /99/ImportSQLTable endpoint using firewall rules or network segmentation
- Implement authentication requirements for all REST API endpoints if not already in place
- Review logs for any historical exploitation attempts targeting this endpoint
Patch Information
The vulnerability has been resolved in H2O-3 version 3.46.0.10. The patch expands the DEFAULT_JDBC_DISALLOWED_PARAMETERS list to include PostgreSQL-specific dangerous parameters including socketFactory, socketFactoryArg, sslfactory, and sslfactoryarg. Additionally, logging-related parameters loggerLevel and loggerFile were added to the blocklist as a defense-in-depth measure. The fix is available in the GitHub commit.
Workarounds
- Block external network access to H2O-3 REST API endpoints using firewall rules until patching is complete
- Implement a reverse proxy with request filtering to block JDBC URLs containing PostgreSQL protocol schemes with dangerous parameters
- Deploy the H2O-3 instance behind an authentication gateway to prevent unauthenticated API access
- Consider temporarily disabling the SQL import functionality if not required for operations
# Example iptables rule to restrict access to H2O-3 default port
iptables -A INPUT -p tcp --dport 54321 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 54321 -j DROP
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

