GHSA-8xwf-rjm4-xvhv
Fix: oras-project/oras-go@cc323e5GHSA-8xwf-rjm4-xvhv is a CWE-73 vulnerability in oras.land/oras-go/v2. O3 Security confirms whether GHSA-8xwf-rjm4-xvhv is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.
oras-go has file store write outside workingDir via symlink traversal
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for GHSA-8xwf-rjm4-xvhv.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Real-World Exposure
oras.land/oras-go/v2Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
The file content store in oras-go attempts to confine writes to workingDir when AllowPathTraversalOnWrite=false, but the guard is lexical and does not account for symlink traversal. If workingDir contains a symlink path component and an attacker-controlled blob title (via ocispec.AnnotationTitle) targets a path under that symlink, pushFile() can create a file outside workingDir.
relevant links
- repository: https://github.com/oras-project/oras-go
- commit: 03243809936cce826494b5506f724c6dc11115b1
- callsite: content/file/file.go:609
resolveWritePath()(used bypushFile())
vulnerability details
pins: oras-project/oras-go@03243809936cce826494b5506f724c6dc11115b1
as-of: 2026-02-17
policy: GitHub Security Advisory (oras-project/oras-go)
callsite: content/file/file.go:609 resolveWritePath() → pushFile()
attacker control: Attacker controls the pushed name (ocispec.AnnotationTitle) and can select a path with a symlink path component under workingDir → resolveWritePath() blocks .. via filepath.Rel but does not prevent symlink traversal → pushFile() opens/creates the final path and follows the symlink → a file is created outside workingDir
root cause
resolveWritePath() enforces the write boundary using a filepath.Rel-style check against workingDir. This prevents ../ escapes but is purely lexical and does not resolve symlinks. If a path component under workingDir is a symlink to an external location, the subsequent filesystem operation in pushFile() follows that symlink and performs the write outside workingDir while still passing the lexical boundary check.
attack path
- Attacker provides a blob title (via
ocispec.AnnotationTitle) that contains a path likeout/pwn.txt. - Victim uses
oras-gofile store withAllowPathTraversalOnWrite=falseand aworkingDirthat contains a symlink directoryout -> /some/outside/dir. - The lexical boundary check accepts
out/pwn.txtas being underworkingDir. - The write follows the symlink and creates
/some/outside/dir/pwn.txt.
impact
This is a filesystem boundary bypass that permits writes outside workingDir when a symlink path component exists under workingDir. The concrete security impact depends on the runtime environment (what filesystem locations are writable by the process and what downstream consumers do with the written file), but the intended confinement guarantee is violated.
proof of concept
the attached poc.zip contains a small, self-contained go harness that demonstrates:
- canonical (vulnerable): prints
[CALLSITE_HIT]and[PROOF_MARKER]and shows the file is created outsideworkingDir - control (no symlink component): prints
[NC_MARKER]and confirms no outside write occurs
run:
unzip -q -o poc.zip -d /tmp
cd /tmp/poc-F-ORAS-SYMLINK-WRITE-001
make test
expected: when AllowPathTraversalOnWrite=false, file store writes should not be able to escape workingDir, including via symlink traversal.
actual: A symlink path component under workingDir allows writes to escape workingDir even when AllowPathTraversalOnWrite=false.
recommended fix
ensure confinement checks account for symlink traversal. Options include rejecting symlinks in any path component (walk components with os.Lstat), validating the resolved parent directory via EvalSymlinks and enforcing it remains under the resolved workingDir, or using an openat()-style approach so the check and open happen relative to a trusted directory file descriptor.
fix accepted when: The canonical PoC no longer prints [PROOF_MARKER] for the same attacker-controlled inputs.
cheers, Oleh
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | oras.land/oras-go/v2 | all versions | 2.6.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for oras.land/oras-go/v2. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update oras.land/oras-go/v2 to 2.6.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-8xwf-rjm4-xvhv is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-8xwf-rjm4-xvhv is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-8xwf-rjm4-xvhv. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
Frequently Asked Questions
Is GHSA-8xwf-rjm4-xvhv in your dependencies?
O3 detects GHSA-8xwf-rjm4-xvhv across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.