Mar 5, 2026·5 min read·26 visits
dbt-common incorrectly uses string prefix matching to validate file paths during tarball extraction. Attackers can bypass this check using crafted paths (e.g., `/target_evil` vs `/target`) to write files outside the intended directory. Fixed in versions 1.34.2 and 1.37.3.
A path traversal vulnerability exists in the `dbt-common` Python package due to insecure usage of `os.path.commonprefix` during archive extraction. This flaw allows malicious tarballs to bypass directory confinement checks and write files to sibling directories of the intended destination. The vulnerability affects versions prior to 1.34.2 and versions between 1.35.0 and 1.37.3. It arises from a logic error where string prefix matching is used instead of path component comparison, effectively neutralizing the sandbox check intended to prevent arbitrary file writes.
The dbt-common package, a foundational library for the dbt (Data Build Tool) ecosystem, contains a path traversal vulnerability within its safe_extract() utility. This function is designed to unpack tarball archives securely by ensuring that all extracted files reside strictly within a specified target directory. However, the implementation of this boundary check was flawed due to the misuse of the Python standard library function os.path.commonprefix.
This vulnerability is technically indistinguishable from CVE-2026-1703, a similar flaw identified in the pip package manager. Both vulnerabilities stem from the misconception that commonprefix operates on path components (directories), whereas it actually operates on raw strings. This distinction allows an attacker to construct a path that matches the characters of the target directory's name but extends into a sibling directory, thereby bypassing the confinement check.
The impact is categorized as a partial integrity violation. An attacker who can convince a user to install a malicious dbt package or process a crafted tarball can write files to arbitrary locations on the disk, provided those locations share a string prefix with the intended destination or if the attacker utilizes specific traversal techniques relative to that prefix. This can lead to the overwriting of configuration files or the planting of malicious scripts in adjacent directories.
The root cause of this vulnerability lies in the _is_within_directory helper function located in dbt_common/clients/system.py. The function attempts to verify that a file path falls under a parent directory by comparing the common prefix of the two absolute paths. The vulnerable logic is implemented as follows:
prefix = os.path.commonprefix([abs_directory, abs_target])
return prefix == abs_directoryThe Python documentation for os.path.commonprefix explicitly states that it returns the "longest string prefix," acting on a character-by-character basis. It does not respect directory separators. Consequently, if the intended destination is /usr/local/dbt/packages and the malicious path is /usr/local/dbt/packages_evil/exploit.sh, the common prefix is calculated as /usr/local/dbt/packages.
Since the calculated prefix matches the authorized abs_directory, the function returns True, erroneously confirming that the file is safe to extract. The operating system, however, treats packages and packages_evil as two distinct, sibling directories. This discrepancy between the validator's string-based logic and the filesystem's path-based logic creates the traversal primitive.
The remediation involves replacing os.path.commonprefix with os.path.commonpath. Introduced in Python 3.5, commonpath correctly handles filesystem paths by returning the longest common sub-path, respecting directory separators. If paths are on different drives or do not share a common root, it raises a ValueError.
Below is the comparison of the vulnerable and patched code in dbt_common/clients/system.py:
Vulnerable Implementation:
def _is_within_directory(directory, target):
abs_directory = os.path.abspath(directory)
abs_target = os.path.abspath(target)
# FLAW: Character-wise comparison ignores directory boundaries
prefix = os.path.commonprefix([abs_directory, abs_target])
return prefix == abs_directoryPatched Implementation (Commit e547954):
def _is_within_directory(directory, target):
abs_directory = os.path.abspath(directory)
abs_target = os.path.abspath(target)
try:
# FIX: Component-wise comparison respects directory boundaries
prefix = os.path.commonpath([abs_directory, abs_target])
return prefix == abs_directory
except ValueError:
# Handles cases like different drives on Windows
return FalseIn the patched version, comparing /tmp/pkg and /tmp/pkgevil using commonpath returns /tmp. Since /tmp does not equal /tmp/pkg, the check fails (False), and the extraction is aborted, preventing the traversal.
To exploit this vulnerability, an attacker must craft a malicious tarball (.tar.gz) containing file entries with manipulated paths. The exploit relies on the fact that dbt packages are often installed via URLs or Git repositories, which dbt-common processes.
The attack flow is as follows:
.../dbt_packages/target, the attacker names the file inside the archive ../target_suffix/malicious_file. When resolved absolutely, if the prefix matches, the check passes.dbt deps or installs the package. The untar_package function invokes _is_within_directory, which returns True for the malicious path.The accompanying Proof-of-Concept (PoC) from the unit tests demonstrates this explicitly:
# Creating a malicious path that is a sibling with a shared prefix
sibling_path = "../" + os.path.basename(self.tempdest) + "evil/malicious.txt"
with tarfile.open(fileobj=named_tar_file, mode="w:gz") as tar:
tar.addfile(tarfile.TarInfo(sibling_path), open(file_a.name))When this archive is extracted against self.tempdest, the file is written to self.tempdest + "evil", successfully escaping the sandbox.
The impact of this vulnerability is classified as Medium (CVSS 4.0 Score: 4.0). While it allows for arbitrary file writes, several mitigating factors limit the severity compared to a critical Remote Code Execution (RCE) flaw.
CVSS Vector: CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
Despite the "Medium" rating, in automated CI/CD environments where dbt runs might occur with elevated privileges or where the filesystem is shared across pipeline stages, this could facilitate lateral movement or persistence.
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
dbt-common dbt Labs | < 1.34.2 | 1.34.2 |
dbt-common dbt Labs | >= 1.35.0, < 1.37.3 | 1.37.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| CWE Name | Improper Limitation of a Pathname to a Restricted Directory |
| CVSS Score | 4.0 (Medium) |
| CVSS Vector | CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N |
| Exploit Maturity | Proof of Concept (PoC) |
| Patch Status | Available (1.34.2, 1.37.3) |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
A CSV Formula Injection vulnerability (CWE-1236) exists in the Spree headless eCommerce platform within the customer export functionality. An unauthenticated attacker can register a customer profile containing malicious formula sequences in fields like the first name or last name. When an administrator exports the customer data to a CSV file and opens it in a spreadsheet application, the spreadsheet engine can interpret and execute these formulas, potentially leading to remote command execution on the administrator's workstation or out-of-band data exfiltration.
A Stored Cross-Site Scripting (XSS) vulnerability exists in WWBN AVideo versions up to and including 29.0. Unsanitized category descriptions are stored in the database and subsequently rendered as raw HTML in the Gallery view plugin, allowing low-privileged authenticated users to execute arbitrary JavaScript in the browsers of visiting users.
A critical supply chain compromise was identified in the Node.js package @cap-js/openapi at version 1.4.1. An attacker gained unauthorized publishing access to the npm registry and distributed a backdoored release that harvests sensitive developer credentials, environment variables, and SSH keys. The malicious code then exfiltrates the collected data to external actor-controlled servers.
An authenticated wallet credit bypass vulnerability exists in WWBN AVideo version 29.0 and earlier. The AuthorizeNet plugin includes an unfinished mockup endpoint, processPayment.json.php, which lacks actual transaction verification and hardcodes success. This allows any authenticated user to credit their wallet with arbitrary balances without making any payments.
An unauthenticated stored DOM-based Cross-Site Scripting (DOM XSS) vulnerability in the YPTSocket plugin of WWBN AVideo (formerly YouPHPTube) allows remote attackers to execute arbitrary JavaScript within the session context of administrative users. Unsanitized metadata parameters supplied during the WebSocket handshake are persisted in an SQLite database and broadcast to connected users. The frontend application processes these parameters through an unsafe jQuery append sink, leading to silent, high-impact administrative context compromise.
A path parsing and normalization inconsistency vulnerability exists in the Hono web framework prior to version 4.12.21. When hosting sub-applications via the app.mount() routing interface, Hono calculates the routing path prefix length on a percent-decoded representation of the URI but executes the path-slicing offset on the raw, percent-encoded string. This discrepancy results in malformed request paths being dispatched to mounted sub-applications, potentially leading to route bypasses, route confusion, and application-level Denial of Service.