CVE-2026-50162: Oras.land/oras go/v2 Oras-go Has File Store Write Vulnerability

MODERATE
Advisory Identifier: GHSA-8xwf-rjm4-xvhv
CWE-73
Published
Advisory Summary

CVE-2026-50162 is a MODERATE oras-go has file store write vulnerability (CWE-73: External Control of File Name or Path) affecting Oras.land/oras go/v2 libraries in the Go ecosystem. The issue involves oras-go has file store write outside workingdir via symlink traversal. Remediation is available by upgrading affected packages to version 2.6.1.

CVE-2026-50162 at a Glance

CVE Identifier CVE-2026-50162
GHSA Identifier GHSA-8xwf-rjm4-xvhv
Severity MODERATE
CVSS v3.1 Base Score N/A
CWE Classification CWE-73: External Control of File Name or Path
Affected Product Oras.land/oras go/v2
Package Ecosystem Go
Published Date
Last Updated

How to Fix CVE-2026-50162

To remediate this vulnerability, upgrade all affected Oras.land/oras go/v2 dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

oras.land/oras-go/v2 fixed: 2.6.1
Upgrade oras.land/oras-go/v2 to 2.6.1
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for oras.land/oras-go/v2

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-50162, inspect your project dependencies for Oras.land/oras go/v2:

inspect dependencies for oras.land/oras-go/v2

Analyze the terminal output to locate any version of Oras.land/oras go/v2 in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.6.1), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-73: External Control of File Name or Path, where the product allows user input to control or influence paths or file names that are used in filesystem operations. In Oras.land/oras go/v2, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

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 by `pushFile()`) ## 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 1. Attacker provides a blob title (via `ocispec.AnnotationTitle`) that contains a path like `out/pwn.txt`. 2. Victim uses `oras-go` file store with `AllowPathTraversalOnWrite=false` and a `workingDir` that contains a symlink directory `out -> /some/outside/dir`. 3. The lexical boundary check accepts `out/pwn.txt` as being under `workingDir`. 4. 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 outside `workingDir` - control (no symlink component): prints `[NC_MARKER]` and confirms no outside write occurs run: ```bash 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

CVE-2026-50162 Affected Oras.land/oras go/v2 Versions

1 component(s)
Fixed Versions:
2.6.1
Product / Package Ecosystem Affected Versions Fixed Version
oras.land/oras-go/v2
Go
< 2.6.1
2.6.1

References

Frequently Asked Questions

What is CVE-2026-50162?
CVE-2026-50162 is a security vulnerability in Oras.land/oras go/v2 involving oras-go has file store write outside workingDir via symlink traversal under CWE-73: External Control of File Name or Path.
Which Oras.land/oras go/v2 versions are affected?
Affected versions include releases prior to 2.6.1 across affected packages: oras.land/oras-go/v2.
What version fixes CVE-2026-50162?
Upgrading to 2.6.1 (or the latest patched release for your respective branch) resolves the vulnerability.
Is oras.land/oras-go/v2 affected?
Yes, oras.land/oras-go/v2 is affected in releases prior to 2.6.1. Upgrade your dependency to 2.6.1 or later.
What CWE is associated with CVE-2026-50162?
CVE-2026-50162 is classified under CWE-73: External Control of File Name or Path (The product allows user input to control or influence paths or file names that are used in filesystem operations.).
How can I check Go dependencies for CVE-2026-50162?
Run the dependency tree command: 'inspect dependencies for oras.land/oras-go/v2'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-8xwf-rjm4-xvhv",
  "modified" : "2026-07-01T21:43:11Z",
  "published" : "2026-07-01T21:43:10Z",
  "aliases" : [ "CVE-2026-50162" ],
  "summary" : "oras-go has file store write outside workingDir via symlink traversal",
  "details" : "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`.\n\n## relevant links\n\n- repository: https://github.com/oras-project/oras-go\n- commit: 03243809936cce826494b5506f724c6dc11115b1\n- callsite: content/file/file.go:609 `resolveWritePath()` (used by `pushFile()`)\n\n## vulnerability details\n\n**pins:** oras-project/oras-go@03243809936cce826494b5506f724c6dc11115b1\n\n**as-of:** 2026-02-17\n\n**policy:** GitHub Security Advisory (oras-project/oras-go)\n\n**callsite:** content/file/file.go:609 `resolveWritePath()` → `pushFile()`\n\n**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`\n\n### root cause\n\n`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.\n\n### attack path\n\n1. Attacker provides a blob title (via `ocispec.AnnotationTitle`) that contains a path like `out/pwn.txt`.\n2. Victim uses `oras-go` file store with `AllowPathTraversalOnWrite=false` and a `workingDir` that contains a symlink directory `out -> /some/outside/dir`.\n3. The lexical boundary check accepts `out/pwn.txt` as being under `workingDir`.\n4. The write follows the symlink and creates `/some/outside/dir/pwn.txt`.\n\n## impact\n\nThis 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.\n\n## proof of concept\n\nthe attached `poc.zip` contains a small, self-contained go harness that demonstrates:\n\n- canonical (vulnerable): prints `[CALLSITE_HIT]` and `[PROOF_MARKER]` and shows the file is created outside `workingDir`\n- control (no symlink component): prints `[NC_MARKER]` and confirms no outside write occurs\n\nrun:\n\n```bash\nunzip -q -o poc.zip -d /tmp\ncd /tmp/poc-F-ORAS-SYMLINK-WRITE-001\nmake test\n```\n\n**expected:** when `AllowPathTraversalOnWrite=false`, file store writes should not be able to escape `workingDir`, including via symlink traversal.\n\n**actual:** A symlink path component under `workingDir` allows writes to escape `workingDir` even when `AllowPathTraversalOnWrite=false`.\n\n## recommended fix\n\nensure 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.\n\n**fix accepted when:** The canonical PoC no longer prints `[PROOF_MARKER]` for the same attacker-controlled inputs.\n\n\ncheers,\nOleh",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "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"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "oras.land/oras-go/v2"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "2.6.1"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/oras-project/oras-go/security/advisories/GHSA-8xwf-rjm4-xvhv"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/oras-project/oras-go/commit/cc323e564d90c6b5b4bdd71d3c8d2ee2713b37e5"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/oras-project/oras-go"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-73" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-01T21:43:10Z",
    "nvd_published_at" : null
  }
}