Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network delivery of malicious OCI artifact (AV:N); symlink prerequisite in workingDir raises complexity (AC:H); no victim-system privileges needed (PR:N); victim must pull artifact (UI:R); write escapes workingDir boundary into broader filesystem (S:C); no read impact (C:N); arbitrary file write is high integrity (I:H); incidental overwrite risk (A:L).
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Primary rating from Vendor (https://github.com/oras-project/oras-go).
CVSS VectorVendor: https://github.com/oras-project/oras-go
Lifecycle Timeline
2DescriptionCVE.org
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 testexpected: 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
AnalysisAI
Symlink traversal in oras-go's file content store allows writes outside the intended workingDir boundary even when AllowPathTraversalOnWrite=false. Applications that pull OCI artifacts from untrusted registries where an attacker controls blob titles (ocispec.AnnotationTitle) are at risk if any directory component under workingDir is a symlink pointing to an external path. No confirmed active exploitation (not in CISA KEV), but a self-contained proof-of-concept was included in the researcher's disclosure, making reproduction straightforward given the prerequisites.
Technical ContextAI
oras-go is the canonical Go library implementing OCI Registry As Storage (ORAS), used by tooling that reads and writes OCI artifacts to and from registries. The vulnerable codepath is content/file/file.go:609 inside resolveWritePath(), which is invoked by pushFile() during blob materialization. When a blob is written to the file store, resolveWritePath() enforces the workingDir confinement boundary using a filepath.Rel-style lexical comparison to reject ../ escapes (CWE-73: External Control of File Name or Path). Critically, this check operates purely on the string representation of the path and never calls filepath.EvalSymlinks() or walks components with os.Lstat. Consequently, a path like out/pwn.txt clears the lexical guard even if out is a symlink to /external/dir; the subsequent os.Open/os.Create call in pushFile() follows the symlink at the OS level, materializing the file at /external/dir/pwn.txt. The affected package is oras.land/oras-go/v2 (CPE: pkg:go/oras.land_oras-go_v2).
RemediationAI
The upstream fix is available at commit cc323e564d90c6b5b4bdd71d3c8d2ee2713b37e5 (https://github.com/oras-project/oras-go/commit/cc323e564d90c6b5b4bdd71d3c8d2ee2713b37e5); consumers should update their go.mod to a tagged release that includes this commit - verify inclusion via git log against the fix SHA, as a specific released version number is not confirmed in the available advisory data. As a compensating control, audit workingDir for symlink components using find $workingDir -type l and replace any symlink directories with real directories; this eliminates the traversal surface entirely without a library update, though it requires ongoing operational governance to enforce. A second mitigation is to restrict OCI pulls exclusively to internal, access-controlled registries, preventing attacker-controlled ocispec.AnnotationTitle values from reaching the vulnerable codepath - note this has the trade-off of blocking legitimate third-party artifact consumption. Do not rely on AllowPathTraversalOnWrite=false alone as a security boundary until the fix is applied, as this flag's protection is currently bypassed by symlink traversal.
The x86-64 kernel system-call functionality in Xen 4.1.2 and earlier, as used in Citrix XenServer 6.0.2 and earlier and
An authenticated path traversal vulnerability in Langflow's file upload functionality allows attackers to write arbitrar
Arbitrary host file write in Incus before 7.1.0 lets a holder of S3 bucket credentials escape the storage volume via a p
Canonical snapd before version 2.37.1 incorrectly performed socket owner validation, allowing an attacker to run arbitra
An authorization bypass vulnerability in gRPC-Go allows attackers to circumvent path-based access control by sending HTT
Server-side request forgery in the Ruby css_parser gem (< 3.0.0) lets a remote unauthenticated attacker force the parsin
Arbitrary file read in Langroid's SQLChatAgent (<= 0.63.0) lets an attacker who can influence the LLM-generated SQL exfi
Authentication bypass in the joserfc Python JOSE/JWT library (PyPI, versions <= 1.6.7) lets unauthenticated attackers fo
SSRF in the Bifrost AI gateway's multimodal URL-fetch path permits any client that can submit a Bedrock or Vertex provid
URLSecurityValidator SSRF bypass in compliance-trestle <= 4.0.3 allows a network-positioned attacker to reach cloud meta
Path traversal in rclone's `serve restic` REST API allows any attacker with network access to the endpoint to read, crea
Credential leakage in elixir-tesla (Tesla HTTP client for Elixir) versions 1.4.0 through 1.18.2 allows Authorization and
Same weakness CWE-73 – External Control of File Name or Path
View allSame technique Authentication Bypass
View allVendor StatusVendor
SUSE
Severity: ModerateShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-45262
GHSA-8xwf-rjm4-xvhv