CVE-2025-8406 Overview
CVE-2025-8406 is a path traversal vulnerability in ZenML version 0.83.1, affecting the PathMaterializer class. The load function relies on is_path_within_directory to validate files extracted from data.tar.gz archives. This check fails to account for symbolic and hard links inside the archive. An attacker who supplies a crafted archive can write arbitrary files outside the intended extraction directory. When critical files are overwritten, this can escalate to arbitrary command execution on the host running ZenML.
Critical Impact
A malicious tar archive can trigger arbitrary file writes outside the extraction directory, enabling code execution if system or application files are overwritten.
Affected Products
- ZenML 0.83.1
- ZenML PathMaterializer component
- Pipelines consuming untrusted data.tar.gz archives
Discovery Timeline
- 2025-10-05 - CVE-2025-8406 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-8406
Vulnerability Analysis
ZenML uses the PathMaterializer class to serialize and deserialize Path objects during pipeline execution. During deserialization, the load function extracts a data.tar.gz archive into a target directory. Before extraction, each tar member name is checked with is_path_within_directory to confirm the path stays inside the destination.
The validation covers regular file names but does not inspect link targets. Tar archives can contain symbolic links (issym()) and hard links (islnk()) whose linkname attribute points to an arbitrary location. Because the original check ignored linkname, an attacker could stage a link inside the archive that references files outside the extraction root. Subsequent writes through that link land on the attacker-chosen path, classifying this as a path traversal issue [CWE-22] with symlink and hard link attack characteristics.
Root Cause
The root cause is incomplete tar member validation. is_path_within_directory was applied only to member.name, not to member.linkname. Symbolic and hard link members bypassed the containment check entirely, allowing writes to escape the extraction directory.
Attack Vector
Exploitation requires the ZenML process to load a malicious data.tar.gz produced or influenced by the attacker, and user interaction to trigger the pipeline step that invokes PathMaterializer.load. Once loaded, the crafted archive can overwrite configuration files, scheduled task definitions, or Python modules the ZenML process later executes, leading to command execution in the pipeline user's context.
# Security patch in src/zenml/materializers/path_materializer.py
# Source: https://github.com/zenml-io/zenml/commit/5d22a48d7bf6c7f10b748577c2be79cc7969d398
from zenml.utils.io_utils import is_path_within_directory
def _is_safe_tar_member(member: tarfile.TarInfo, directory: str) -> bool:
"""Check if a tar member is safe to extract.
This function validates that the member name and any link targets
are within the specified directory to prevent path traversal attacks.
Args:
member: The tar member to validate.
directory: The target extraction directory.
Returns:
True if the member is safe to extract, False otherwise.
"""
# Check if the member name is within the directory
if not is_path_within_directory(member.name, directory):
return False
# For symbolic links and hard links, validate the target path
if member.issym() or member.islnk():
return is_path_within_directory(member.linkname, directory)
return True
class PathMaterializer(BaseMaterializer):
"""Materializer for Path objects."""
The patch introduces _is_safe_tar_member, which validates both member.name and, for symlink or hardlink members, the linkname target before extraction proceeds.
Detection Methods for CVE-2025-8406
Indicators of Compromise
- Unexpected data.tar.gz artifacts in ZenML pipeline inputs originating from untrusted sources.
- New or modified files outside the ZenML working directory following pipeline execution, particularly in user home directories, ~/.ssh/, or Python site-packages.
- Tar archives containing members where issym() or islnk() returns true and linkname points to absolute paths or paths containing ../ sequences.
- ZenML processes spawning unexpected child processes after loading a Path artifact.
Detection Strategies
- Inspect archives referenced by PathMaterializer.load and enumerate tar members with link targets outside the destination directory.
- Monitor file integrity on ZenML host directories that fall outside pipeline scratch space, alerting on writes originating from the ZenML process.
- Baseline the ZenML process tree and alert on deviations such as shell invocations or new outbound network connections.
Monitoring Recommendations
- Enable audit logging for file writes performed by the user account running ZenML pipelines.
- Track version pinning for ZenML across build and runtime environments to identify hosts still running 0.83.1.
- Correlate pipeline execution logs with filesystem telemetry to surface writes outside expected artifact directories.
How to Mitigate CVE-2025-8406
Immediate Actions Required
- Upgrade ZenML to a version that includes commit 5d22a48d7bf6c7f10b748577c2be79cc7969d398, which adds _is_safe_tar_member validation.
- Restrict pipeline execution accounts to the minimum filesystem privileges needed for artifact directories.
- Reject or quarantine data.tar.gz inputs sourced from untrusted contributors or public artifact stores.
Patch Information
The fix is published in the ZenML repository commit zenml-io/zenml@5d22a48. Additional context is available in the Huntr Bounty Listing. Upgrade to a ZenML release that includes this commit.
Workarounds
- Run ZenML pipelines inside isolated containers or ephemeral VMs so that arbitrary writes cannot reach host configuration files.
- Pre-scan incoming tar archives and reject any member where issym() or islnk() is true and linkname resolves outside the extraction directory.
- Store pipeline artifacts on dedicated volumes mounted read-only for paths that must not be altered by pipeline execution.
# Inspect a tar archive for unsafe link members before allowing ZenML to load it
tar -tvf data.tar.gz | awk '$1 ~ /^l/ || $1 ~ /^h/ {print}'
# Upgrade ZenML to a patched release
pip install --upgrade zenml
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

