yawkat LZ4 Java: Native library extraction to a shared temporary directory is vulnerable to file replacement by another local user
### Summary When no system-installed `liblz4-java` is found, `net.jpountz.util.Native.load()` extracts the bundled native library to `java.io.tmpdir` and loads it with `System.load`. The path of the extracted library can be predicted before it is created, and the library file is opened without exclusive creation. Another local user who can write to the same temporary directory can therefore create the file first and control the code that is loaded. ### Details ```java tempLibLock = File.createTempFile("liblz4-java-", "." + os().libExtension + ".lck"); tempLib = new File(tempLibLock.getAbsolutePath().replaceFirst(".lck$", "")); // copy to tempLib try (FileOutputStream out = new FileOutputStream(tempLib)) { ... } ... System.load(tempLib.getAbsolutePath()); ``` Only the `.lck` file is created safely, with a random name and exclusive creation. The library path is the `.lck` name without the `.lck` suffix, and nothing reserves it. `new FileOutputStream(tempLib)` opens it with `O_CREAT|O_TRUNC` and follows symlinks. In a shared, world-writable temporary directory, another user can watch for the `.lck` file and create the corresponding library file before it is opened. If they win that race, they own the file. The victim then writes into the attacker-owned file, and the attacker can overwrite it again before `System.load`. Whether this can be exploited depends on the host: - With `fs.protected_regular = 0`, the attacker can pre-create a world-writable file, and their code is then lo
- Products
- at.yawk.lz4:lz4-java, org.lz4:lz4-java
- Affected versions
- 1.10.0, 1.10.1, 1.10.2, 1.10.3, 1.10.4, 1.11.0, 1.11.1, 1.11.2, 1.11.3, 1.7.0, 1.7.1, 1.8.0, 1.8.1, 1.9.0
- Fixed versions
- 1.11.4
- CVEs
- CVE-2026-106451
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 28 Oct 2026, 08:48 UTC · Revision 1
Source evidence
yawkat LZ4 Java: Native library extraction to a shared temporary directory is vulnerable to file replacement by another local user
core-osv · Original sourcePublished 7 Oct 2026, 20:35 UTC
### Summary When no system-installed `liblz4-java` is found, `net.jpountz.util.Native.load()` extracts the bundled native library to `java.io.tmpdir` and loads it with `System.load`. The path of the extracted library can be predicted before it is created, and the library file is opened without exclusive creation. Another local user who can write to the same temporary directory can therefore create the file first and control the code that is loaded. ### Details ```java tempLibLock = File.createTempFile("liblz4-java-", "." + os().libExtension + ".lck"); tempLib = new File(tempLibLock.getAbsolutePath().replaceFirst(".lck$", "")); // copy to tempLib try (FileOutputStream out = new FileOutputStream(tempLib)) { ... } ... System.load(tempLib.getAbsolutePath()); ``` Only the `.lck` file is created safely, with a random name and exclusive creation. The library path is the `.lck` name without the `.lck` suffix, and nothing reserves it. `new FileOutputStream(tempLib)` opens it with `O_CREAT|O_TRUNC` and follows symlinks. In a shared, world-writable temporary directory, another user can watch for the `.lck` file and create the corresponding library file before it is opened. If they win that race, they own the file. The victim then writes into the attacker-owned file, and the attacker can overwrite it again before `System.load`. Whether this can be exploited depends on the host: - With `fs.protected_regular = 0`, the attacker can pre-create a world-writable file, and their code is then lo
osv:GHSA-mcr4-qmvw-px4g
at.yawk.lz4:lz4-java
Fixed versions: 1.11.4
org.lz4:lz4-java
Fixed versions: Not specified
Complete source record
{
"id": "a8d1efc1ab044f078c01c9d858bbc73b1af5c676bed8842db7645c1ff2560f73",
"url": "https://osv.dev/vulnerability/GHSA-mcr4-qmvw-px4g",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "yawkat LZ4 Java: Native library extraction to a shared temporary directory is vulnerable to file replacement by another local user",
"summary": "### Summary When no system-installed `liblz4-java` is found, `net.jpountz.util.Native.load()` extracts the bundled native library to `java.io.tmpdir` and loads it with `System.load`. The path of the extracted library can be predicted before it is created, and the library file is opened without exclusive creation. Another local user who can write to the same temporary directory can therefore create the file first and control the code that is loaded. ### Details ```java tempLibLock = File.createTempFile(\"liblz4-java-\", \".\" + os().libExtension + \".lck\"); tempLib = new File(tempLibLock.getAbsolutePath().replaceFirst(\".lck$\", \"\")); // copy to tempLib try (FileOutputStream out = new FileOutputStream(tempLib)) { ... } ... System.load(tempLib.getAbsolutePath()); ``` Only the `.lck` file is created safely, with a random name and exclusive creation. The library path is the `.lck` name without the `.lck` suffix, and nothing reserves it. `new FileOutputStream(tempLib)` opens it with `O_CREAT|O_TRUNC` and follows symlinks. In a shared, world-writable temporary directory, another user can watch for the `.lck` file and create the corresponding library file before it is opened. If they win that race, they own the file. The victim then writes into the attacker-owned file, and the attacker can overwrite it again before `System.load`. Whether this can be exploited depends on the host: - With `fs.protected_regular = 0`, the attacker can pre-create a world-writable file, and their code is then lo",
"evidence": "osv:GHSA-mcr4-qmvw-px4g",
"products": [
{
"name": {
"value": "at.yawk.lz4:lz4-java",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.11.4",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": [
{
"value": "1.10.0",
"evidence": "/affected/0/versions"
},
{
"value": "1.10.1",
"evidence": "/affected/0/versions"
},
{
"value": "1.10.2",
"evidence": "/affected/0/versions"
},
{
"value": "1.10.3",
"evidence": "/affected/0/versions"
},
{
"value": "1.10.4",
"evidence": "/affected/0/versions"
},
{
"value": "1.11.0",
"evidence": "/affected/0/versions"
},
{
"value": "1.11.1",
"evidence": "/affected/0/versions"
},
{
"value": "1.11.2",
"evidence": "/affected/0/versions"
},
{
"value": "1.11.3",
"evidence": "/affected/0/versions"
},
{
"value": "1.8.1",
"evidence": "/affected/0/versions"
},
{
"value": "1.9.0",
"evidence": "/affected/0/versions"
}
]
},
{
"name": {
"value": "org.lz4:lz4-java",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [],
"affected_versions": [
{
"value": "1.7.0",
"evidence": "/affected/1/versions"
},
{
"value": "1.7.1",
"evidence": "/affected/1/versions"
},
{
"value": "1.8.0",
"evidence": "/affected/1/versions"
},
{
"value": "1.8.1",
"evidence": "/affected/1/versions"
}
]
}
],
"severity": "high",
"structured": {
"id": "GHSA-mcr4-qmvw-px4g",
"aliases": [
"CVE-2026-106451",
"GHSA-mcr4-qmvw-px4g"
],
"metrics": [
{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:L/AC:H/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
}
],
"affected": [
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0"
},
{
"fixed": "1.11.4"
}
]
}
],
"package": {
"name": "at.yawk.lz4:lz4-java",
"purl": "pkg:maven/at.yawk.lz4/lz4-java",
"ecosystem": "Maven"
},
"versions": [
"1.10.0",
"1.10.1",
"1.10.2",
"1.10.3",
"1.10.4",
"1.11.0",
"1.11.1",
"1.11.2",
"1.11.3",
"1.8.1",
"1.9.0"
],
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-mcr4-qmvw-px4g/GHSA-mcr4-qmvw-px4g.json",
"last_known_affected_version_range": "<= 1.11.3"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "1.7.0"
},
{
"last_affected": "1.8.1"
}
]
}
],
"package": {
"name": "org.lz4:lz4-java",
"purl": "pkg:maven/org.lz4/lz4-java",
"ecosystem": "Maven"
},
"versions": [
"1.7.0",
"1.7.1",
"1.8.0",
"1.8.1"
],
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-mcr4-qmvw-px4g/GHSA-mcr4-qmvw-px4g.json"
}
}
],
"modified": "2026-10-07T20:45:06.908713391Z",
"provider": "osv",
"references": [
"https://github.com/yawkat/lz4-java/security/advisories/GHSA-mcr4-qmvw-px4g",
"https://nvd.nist.gov/vuln/detail/CVE-2026-106451",
"https://github.com/yawkat/lz4-java/commit/7a48b7f6b8099b9dab6541e4ac2ee0979dc55aa3",
"https://github.com/yawkat/lz4-java",
"https://github.com/yawkat/lz4-java/releases/tag/v1.11.4"
],
"provider_metadata": {
"cwe_ids": [
"CWE-367",
"CWE-377"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": "2026-10-06T20:17:27Z",
"github_reviewed_at": "2026-10-07T20:35:51Z"
}
},
"related_cves": [
{
"value": "CVE-2026-106451",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 97273,
"published_at": "2026-10-07T20:35:51+00:00"
}