CVE-2026-60586
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
MySQL Connector/J is the official JDBC Type 4 driver for MySQL, developed and released by the MySQL team at Oracle. It lets Java applications connect to and query MySQL servers over JDBC, and also implements the X DevAPI for document-store access. It is distributed as the Maven artifact com.mysql:mysql-connector-j and is a standard dependency in Java applications that talk to MySQL.
An information exposure vulnerability (CVE-2026-60586) has been identified in the LOAD DATA LOCAL INFILE handling of MySQL Connector/J, which allows attackers to make the client read files from network shares through file: URLs whose paths name a network location. Data read this way is sent to the MySQL server, so it can expose files that the client host can reach but the attacker could not otherwise access.
Per OWASP: Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits.
This issue affects MySQL Connector/J versions 9.7.0 through 9.7.1.
Details
Module Info
- Product: MySQL Connector/J
- Affected packages:
com.mysql:mysql-connector-j - Affected versions: >=9.7.0 <=9.7.1
- GitHub repository: https://github.com/mysql/mysql-connector-j
- Published packages: https://central.sonatype.com/artifact/com.mysql/mysql-connector-j
- Package manager: Maven
- Fixed in:
- OSS MySQL Connector/J 26.7.0
- NES for MySQL Connector/J v8.0.35
Vulnerability Info
This High-severity vulnerability is found in the com.mysql:mysql-connector-j package in MySQL Connector/J versions 9.7.0 through 9.7.1. Oracle rates it CVSS 3.1 7.7 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N).
During LOAD DATA LOCAL INFILE, the MySQL server names the file the client must send. When allowLoadLocalInfileInPath restricts uploads to a directory and allowUrlInLocalInfile is enabled, NativeProtocol.getFileStream() accepts that name as a URL. It checks only that the protocol is file and that the URL host resolves to a loopback address, resolves a local path from the URL to compare with the allowed directory, and then opens the URL itself:
if (allowUrlInLocalInfile.getValue()) {
try {
URL urlFromFileName = new URL(fileName);
if (!urlFromFileName.getProtocol().equalsIgnoreCase("file")) {
throw ExceptionFactory.createException(Messages.getString("MysqlIO.66", new Object[] { urlFromFileName.getProtocol() }),
this.exceptionInterceptor);
}
try {
InetAddress addr = InetAddress.getByName(urlFromFileName.getHost());
if (!addr.isLoopbackAddress()) {
throw ExceptionFactory.createException(Messages.getString("MysqlIO.67", new Object[] { urlFromFileName.getHost() }),
this.exceptionInterceptor);
}
} catch (UnknownHostException e) {
throw ExceptionFactory.createException(Messages.getString("MysqlIO.68", new Object[] { fileName }), e, this.exceptionInterceptor);
}
Path filePath = null;
try {
filePath = Paths.get(urlFromFileName.toURI()).toRealPath();
} catch (InvalidPathException e) {
// Windows paths often can't be extracted, but the URL is still valid.
String pathString = urlFromFileName.getPath();
if (pathString.indexOf(':') != -1 && (pathString.startsWith("/") || pathString.startsWith("\\"))) {
pathString = pathString.replaceFirst("^[/\\\\]*", "");
}
filePath = Paths.get(pathString).toRealPath();
} catch (IllegalArgumentException e) {
// Try the path directly.
filePath = Paths.get(urlFromFileName.getPath()).toRealPath();
}
if (!filePath.startsWith(safePath)) {
throw ExceptionFactory.createException(Messages.getString("MysqlIO.61", new Object[] { filePath, safePath }), this.exceptionInterceptor);
}
return new BufferedInputStream(urlFromFileName.openStream());
} catch (MalformedURLException | URISyntaxException e) {
// Fall back to trying this as a file input stream.
}
}
The host check only looks at the URL's authority. An empty host resolves to a loopback address, so a URL such as file:////host/share/file or one whose path takes the /\\host\share form passes it. Nothing checks whether the URL path itself is a network path, and the path the driver resolves for the directory check is not necessarily the location openStream() opens on these ambiguous Windows forms. A malicious or compromised MySQL server, or an attacker who can influence the requested file name, can therefore make the client open a UNC path on a remote host and upload its contents, reaching data outside the allowed directory and outside the client's own file system. The same code path is present in Connector/J 8.0.33, the base of NES for MySQL Connector/J.
Mitigation
MySQL Connector/J is maintained by Oracle, which ships fixes only in the current Connector/J release line; older lines no longer receive updates. For more information, see the MySQL Product Support EOL Announcements.
Users of the affected components should apply one of the following mitigations:
- Upgrade affected applications to supported versions of MySQL Connector/J.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.