Mar 6, 2026·6 min read·48 visits
Zarf versions prior to 0.73.1 fail to validate symbolic link targets during archive extraction. Attackers can craft malicious packages containing symlinks that point to arbitrary locations on the host filesystem (e.g., /etc/shadow), leading to arbitrary file read or write access when the package is decompressed.
A high-severity path traversal vulnerability exists in the archive extraction component of Zarf, an airgap-native Kubernetes package manager. The flaw allows malicious packages to write files outside the intended extraction directory via unvalidated symbolic links. This vulnerability affects Zarf versions 0.54.0 through 0.73.0 and is remediated in version 0.73.1.
Zarf is a CLI tool used to package, ship, and deploy Kubernetes clusters and applications in air-gapped environments. A core function of Zarf is the archiver component, which handles the compression and decompression of package artifacts (typically tarballs or zip files). CVE-2026-29064 identifies a critical flaw in how this component handles symbolic links during the extraction process.
The vulnerability is a variation of the "Zip Slip" class of path traversal issues. When Zarf extracts an archive, it processes file entries sequentially. If an entry is a symbolic link, Zarf creates it on the filesystem. However, in affected versions, the extraction logic does not properly sanitize or restrict the LinkTarget of these symlinks. This allows a malicious archive to create a symlink that points to a sensitive location on the host system (e.g., /etc/shadow or ~/.ssh/authorized_keys) rather than a file within the extraction sandbox.
While the creation of the symlink itself might be benign, subsequent operations—such as writing to a file that resolves through that symlink—can result in arbitrary file overwrites. Furthermore, if the user or a downstream process interacts with the extracted directory, they may unwittingly access or modify sensitive host files.
The root cause lies in the implementation of the defaultHandler, stripHandler, and filterHandler functions within src/pkg/archive/archive.go. These handlers are responsible for iterating through archive headers and performing filesystem operations based on the entry type.
In the vulnerable code, when a handler encounters a symbolic link (Type Symlink), it extracts the LinkTarget string from the archive header and passes it directly to os.Symlink. While the destination path (dst) is often constructed using filepath.Join, this function only performs lexical cleaning (e.g., removing .. references within the path string) but does not resolve the physical path or validate that the symlink target resides within the intended directory tree.
Specifically, the code lacked a "jail check"—a mechanism to resolve the canonical path of the symbolic link's target and verify it starts with the canonical path of the extraction root. Without this check, a LinkTarget of ../../../../etc/passwd is accepted as valid. When the operating system processes the symlink() syscall, it creates a link on the filesystem that points outside the extraction root, effectively bypassing the application's intended sandbox.
The remediation for this vulnerability leverages the os.Root API introduced in Go 1.24, which provides a robust mechanism for directory-scoped file operations. This approach is superior to traditional string-based sanitization as it enforces boundaries at the file descriptor level.
Vulnerable Logic (Simplified):
The original code relied on standard os package calls that operate on global paths. Note the lack of validation on h.Linkname.
// BEFORE: src/pkg/archive/archive.go
func (h *defaultHandler) Handle(ctx context.Context, header *tar.Header, dst string) error {
target := filepath.Join(dst, header.Name)
// ...
case tar.TypeSymlink:
// Vulnerability: h.Linkname is trusted blindly
if err := os.Symlink(header.Linkname, target); err != nil {
return err
}
// ...
}Patched Logic:
The fix, applied in commit 93f9c33, refactors the extraction to use an os.Root handle. The extraction root is opened once, and all subsequent operations (creating directories, opening files, creating symlinks) are performed relative to this root handle using the root object methods. The OS kernel ensures these operations cannot escape the directory descriptor.
// AFTER: src/pkg/archive/archive.go
func (h *defaultHandler) Handle(ctx context.Context, root *os.Root, header *tar.Header) error {
// 1. Sanitize entry name to prevent absolute paths or drive letters
if err := validateEntryName(header.Name); err != nil {
return err
}
// 2. Use root-scoped methods for filesystem operations
switch header.Typeflag {
case tar.TypeSymlink:
// 3. Additional validation on the symlink target
if err := validateSymlink(header.Linkname); err != nil {
return err
}
// 4. Create symlink relative to the root handle
// The 'root' object enforces the sandbox boundary
if err := root.Symlink(header.Linkname, header.Name); err != nil {
return err
}
}
}Exploiting this vulnerability requires the attacker to create a specially crafted archive (TAR or ZIP) and convince a user to extract it using the zarf tools archiver decompress command. The attack does not require authentication to the system but does require the ability to supply the malicious package.
Step-by-Step Recreation:
/etc/shadow or a sensitive configuration file).ln -s ../../../../../etc/shadow malicious_linktar commands preserve the relative link target.
tar -czf exploit.tar.gz malicious_linkexploit.tar.gz. When the victim runs zarf tools archiver decompress exploit.tar.gz output_dir, Zarf replicates the symlink in output_dir.output_dir/malicious_link now points to /etc/shadow. If the victim (or a script) reads from this file, they read the shadow file. If the archive contained a second entry that wrote data to malicious_link, the extraction process itself would overwrite /etc/shadow.The successful exploitation of CVE-2026-29064 results in a high-impact integrity and confidentiality breach. The specific impact depends on the context in which Zarf is running.
Scenario 1: CI/CD Pipelines Zarf is frequently used in automated pipelines to prepare air-gapped bundles. If a pipeline extracts a malicious package, the attacker could overwrite pipeline configuration files, inject backdoors into build artifacts, or exfiltrate secrets available on the build agent's filesystem.
Scenario 2: Developer Workstations
Developers using Zarf to examine packages locally run the tool with their user privileges. An attacker could overwrite ~/.ssh/authorized_keys to gain persistent access or read ~/.aws/credentials.
CVSS Breakdown (8.2): The vulnerability scores High because the scope is Changed (S:C)—the attack impacts the underlying host operating system, not just the Zarf application. Integrity (I:H) and Confidentiality (C:H) are both rated High due to the potential for arbitrary file access. User Interaction (UI:R) is required, preventing a 9.0+ score.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Zarf Defense Unicorns | >= 0.54.0, < 0.73.1 | 0.73.1 |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-29064 |
| CVSS v3.1 | 8.2 (High) |
| CWE ID | CWE-22 |
| Attack Vector | Local / User Interaction |
| Impact | Arbitrary File Read/Write |
| Affected Versions | 0.54.0 - 0.73.0 |
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.