Executive Summary: Cloud Native Supply Chain Breakout

The Open Container Initiative (OCI) ecosystem and cloud-native software developers have received a critical supply-chain security advisory documenting a severe path traversal vulnerability in oras-go—the official Go library implementing the OCI Registry As Storage (ORAS) specification. Tracked under identifier CVE-2026-85731 (GitHub Advisory GHSA-g7g9-567g-5h2q) and assigned a CVSS v3.1 score of 8.8 High, the flaw enables malicious container artifacts to break out of their designated extraction root directories.

ORAS is a foundational technology embedded across modern DevOps toolchains, Kubernetes package managers (including Helm v3), software bill-of-materials (SBOM) distributors, and major cloud registries such as Amazon Elastic Container Registry (ECR), Azure Container Registry (ACR), Google Artifact Registry (GAR), and Harbor. When client tools utilize oras-go to pull and unpack non-container arbitrary OCI artifacts, flawed symlink validation allows malicious tar archives to overwrite critical host files, configuration scripts, or binary libraries.

Significantly, the vulnerability bypasses explicit security configurations: even when developers explicitly configure AllowPathTraversalOnWrite = false to disallow traversal, the lexical parser flaw fails to prevent filesystem breakout, posing acute remote code execution risks for automated CI/CD runners, Kubernetes operators, and developer workstations.

Technical Dissection: Lexical Symlink Resolution Breakdown

The vulnerability resides in the content/file.Store package of oras-go, specifically within the logic executed when extracting an OCI layer annotated with the unpacking directive:

io.deis.oras.content.unpack: "true"

To prevent path traversal attacks (such as "Zip Slip"), the library attempts to validate that each file extracted from the tar stream remains strictly inside the target destination root (e.g., /tmp/build/artifacts/). However, the implementation performed purely lexical path sanitization using Go's filepath.Join and filepath.Clean:

// Vulnerable extraction pattern in oras-go < 2.6.2
destPath := filepath.Join(extractRoot, header.Name)
cleanDest := filepath.Clean(destPath)

if !strings.HasPrefix(cleanDest, extractRoot) {
    return errors.New("path traversal detected")
}

// OS extraction creates file at destPath without resolving intermediate symlinks
os.WriteFile(destPath, fileData, 0644)

The Multi-Hop Symlink Attack Vector

While lexical checking successfully blocks trivial relative paths such as ../../etc/cron.d/job, it completely fails against intermediate symbolic links created earlier in the archive extraction sequence:

  1. Step 1 (Symlink Creation): The attacker crafts an OCI layer containing a symlink entry named subfolder pointing to /etc/cron.d. Because filepath.Clean("/tmp/build/artifacts/subfolder") resides within the root, the check passes, and the symlink is created on disk.
  2. Step 2 (Traversal Entry): The archive then contains a normal file entry named subfolder/payload.
  3. Step 3 (Lexical Verification): filepath.Join("/tmp/build/artifacts", "subfolder/payload") produces /tmp/build/artifacts/subfolder/payload. Lexically, this string starts with /tmp/build/artifacts, so the security guard approves the operation.
  4. Step 4 (Kernel Dereference): When os.OpenFile or os.WriteFile is called, the Linux virtual file system (VFS) resolves subfolder through the symbolic link, writing payload directly to /etc/cron.d/payload with the privileges of the executing process.

Supply Chain & CI/CD Pipeline Threat Context

In automated cloud build systems (such as GitHub Actions self-hosted runners, Tekton, or GitLab CI), container builders frequently download OCI artifacts from external or third-party registries. Exploitation of CVE-2026-85731 enables an untrusted dependency to overwrite SSH keys (~/.ssh/authorized_keys), hijack build scripts, or inject cron jobs, leading to runner compromise and secret exfiltration.

Defensive Remediation & Upgrade Guide

Software engineers, DevOps practitioners, and cloud infrastructure architects must audit all Go projects utilizing oras-go and implement immediate upgrades.

1. Go Module Dependency Upgrade

Upgrade your project's go.mod to use oras-go v2.6.2 or later. In version 2.6.2, the maintainers implemented secure path resolution utilizing filepath.EvalSymlinks and atomic directory descriptor operations (openat2 with RESOLVE_BENEATH where supported on modern Linux kernels):

# Update oras-go in your Go module
go get -u oras.land/oras-go/v2@v2.6.2
go mod tidy
go mod verify

2. Dependency Audit Across Go Codebases

Audit internal repositories and microservices for vulnerable transitive versions of oras-go using govulncheck:

# Install official Go vulnerability scanner
go install golang.org/x/vuln/cmd/govulncheck@latest

# Run scan across repository workspace
govulncheck ./...

3. Architectural Hardening for CI/CD Runners

  • Rootless Build Execution: Ensure all container extraction and build processes execute within rootless containers (e.g., using Rootless BuildKit or Kaniko) without host volume mounts.
  • Read-Only Root Filesystems: Mount runner root filesystems as read-only (readOnlyRootFilesystem: true) and restrict extraction scratchpads to ephemeral emptyDir memory volumes.
  • Cryptographic Signature Verification: Enforce mandatory cryptographic artifact signing using Sigstore / Cosign or Notation before permitting automatic extraction of OCI layers.