CVE-2026-103754: Ansible-runner: ansible-runner: path traversal and symlink escape in unstream_dir() allows file write outside the target directory
A flaw was found in ansible-runner. The unstreamdir() function, which receives and extracts a streamed zip archive on the worker side of the ansible-runner transmit/worker protocol, re-creates symbolic links from archive content without validating the link target and applies chmod() and utime() to an unsanitized filesystem path derived from the archive member name. A crafted archive processed by a worker that consumes attacker-influenced input can create files, create symbolic links, or change permissions outside the intended target directory, which can be leveraged toward code execution.
Other sources
Reported via the ansible-security list by Liqiang Ji (ISCAS / SQUARE Research Group).
Module: src/ansiblerunner/utils/streaming.py, function unstreamdir().
unstreamdir() performs a custom ("fancy") extraction to preserve permissions and symlinks. Two defects: 1. CWE-59 (link following): a symlink member's target is read verbatim from the archive content and re-created with os.symlink() without validation, so it can point outside targetdirectory (e.g. '../outside' or an absolute path). A subsequent member extracted through that symlink lands outside targetdirectory (arbitrary write escape). 2. CWE-22 (path traversal): outpath = os.path.join(targetdirectory, info.filename) is built from the unsanitized member name. ZipFile.extract() sanitizes the arcname, but os.utime()/os.chmod() operate on the raw outpath, so a member named '../victim' changes mtime/permissions on a file outside targetdirectory.
Exploitability: in the standard AWX/AAP topology the transmit stream is produced by the trusted controller (streamdir only encodes pre-existing symlinks) and the controller->executor path is authenticated, so there this is defense-in-depth hardening. It is directly relevant to deployments that feed untrusted input into ansible-runner's Worker() path.
Upstream: https://github.com/ansible/ansible-runner Fix PR: https://github.com/ansible/ansible-runner/pull/1550 Confirmed present in 2.4.3 and devel.
— Red Hat
Affected Software
Event History
Frequently Asked Questions
Which deployments are exposed?
Workers using the ansible-runner transmit/worker protocol are exposed when they process streamed ZIP archives whose contents are influenced by an attacker. The affected processing occurs in the worker-side unstream_dir() function.
What does an attacker need to exploit this issue?
An attacker needs a way to supply or influence a crafted archive consumed by a worker. The archive can contain symlinks with absolute or parent-directory targets and subsequent entries that write through those links.
What can exploitation do?
A crafted archive can create files or symlinks, or alter permissions outside the intended target directory. This arbitrary write escape can be leveraged toward code execution.