Jul 20, 2026·6 min read·6 visits
Composer versions prior to 2.2.29 and 2.10.2 do not validate metadata from untrusted repositories during dependency resolution, permitting path traversal, arbitrary file writes outside the project directory, and argument injection.
CVE-2026-59948 is a high-severity path traversal and arbitrary file write vulnerability in the Composer dependency manager for PHP. When resolving package dependencies from custom, untrusted repositories, vulnerable versions fail to validate critical metadata like package names, source/dist URLs, and binary paths. An attacker who controls a third-party repository can serve a malicious package structure that escapes the 'vendor/' folder, enabling arbitrary file creation, option injection in VCS commands, and potential local execution.
Composer is the primary dependency manager for the PHP ecosystem, responsible for fetching, resolving, and installing third-party software packages and library trees. The utility is commonly integrated into developer workstations, automation scripts, and continuous integration/continuous deployment (CI/CD) pipelines. To optimize performance, the system exposes an attack surface where repository metadata is queried and loaded from external endpoints before executing local extraction.
The vulnerability classified as CVE-2026-59948 arises when Composer interfaces with configured custom or third-party repositories other than the default public indexes. If an attacker controls or compromises one of these third-party package repositories, they can return manipulated metadata during dependency resolution operations. Because the tool does not perform standard security checks on certain resolved fields at this phase, the application processes insecure parameters.
The technical impact of this vulnerability manifests primarily as path traversal (CWE-22) and out-of-bounds write (CWE-787). Successfully exploiting the vulnerability allows an attacker to write arbitrary files outside the restricted vendor directory on the target host. Additionally, associated vectors in the same transaction path enable option injection in version control command lines and directory traversal inside package executable configuration paths.
The root cause of CVE-2026-59948 resides in Composer's processing pipeline for remote metadata during the resolution phase. To speed up dependency resolution, the system utilizes a high-performance parser class named ArrayLoader when parsing packages returned from configured repositories. This optimization skips several critical security validation checks, such as name sanitization, directory checking, and remote source URL scanning.
When Composer receives a package definition, it processes the corresponding metadata into a local list within the dependency solver framework. In vulnerable versions, the solver transfers these resolved packages into a lock transaction via LockTransaction::setResultPackages without validating whether the package values conform to safe naming schemes. This allows a maliciously constructed package definition to specify a directory-traversing name like vendor/../../escaped-dir.
During the subsequent step of writing the lock file and extracting download archives, the installer derives local file path locations using the unsanitized package names. Since the file paths are computed by appending the unvalidated package name directly to the project root, directory traversal sequences cause the resolved target paths to point outside the intended boundaries. The extraction engine then writes the archive contents directly to these out-of-bounds file system locations.
To understand the technical fix, we analyze the implementation changes introduced in the patch lifecycle. The vulnerability was mitigated by implementing a strict verification gatekeeper inside the dependency resolver layer, ensuring that package metadata is fully validated before any transactions are committed or files are written. The following diagram illustrates the validated execution flow established by the patch:
In the vulnerable codebase, the setResultPackages method in src/Composer/DependencyResolver/LockTransaction.php added packages directly from the solver pool to the result package array. The patch inserts a direct call to a newly designed validation utility before committing the package:
// src/Composer/DependencyResolver/LockTransaction.php (Patched Excerpt)
if ($literal > 0) {
$package = $pool->literalToPackage($literal);
// Re-validate the package structure before committing it to the transaction
ValidatingArrayLoader::validatePackage($package);
$this->resultPackages['all'][] = $package;
}The core of the mitigation is implemented in src/Composer/Package/Loader/ValidatingArrayLoader.php through the static validatePackage method. This function inspects the deserialized package instance, calling hasPackageNamingError to filter out directory traversal payloads. Additionally, it audits the source/dist URLs and binary paths to ensure no parameter starts with a hyphen (blocking option injection) and that binary definitions do not contain double-dot (..) segments.
Exploitation of CVE-2026-59948 requires a specific pre-configuration where the victim has explicitly registered an untrusted or compromised custom package repository in their project's composer.json file. The attacker must possess administrative control over this repository or execute a man-in-the-middle (MITM) attack to manipulate the HTTP payloads served by the endpoint. Once these requirements are met, the attack proceeds entirely via the metadata transfer phase.
The attacker constructs a package definition containing directory traversal sequences in the name element. When the victim initiates dependency resolution by invoking the composer update or composer install command, Composer requests package definitions from the malicious endpoint. The tool resolves the dependency hierarchy, parses the payload with the unvalidated array loader, and inserts the traversal path directly into the transaction metadata block.
During the final installation phase, Composer downloads the corresponding distribution ZIP archive specified in the metadata and computes the destination path. Due to the directory traversal sequence, the destination path points to a folder outside of the vendor/ sandbox, such as a system directory or a user startup directory. The extraction routine executes, placing the payload files into the designated path and completing the arbitrary file write attack.
The impact of successful exploitation is severe, leading to potential local code execution (RCE) on the developer workstation or CI/CD runner. By writing arbitrary files outside the project root, an attacker can overwrite existing system utilities, inject malicious scripts into startup folders, or plant web shells in publicly accessible directories. The compromise extends to any environment executing the vulnerable dependency manager.
The CVSS v3.1 base score for this vulnerability is assessed at 7.0, indicating a high-severity vulnerability. The metric vector is evaluated as CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H. The Local (L) attack vector reflects that the execution must occur on the victim's machine, and the High (H) complexity indicates the prerequisite of targeting custom, non-default repositories.
Because this vulnerability also facilitates command option injection in the VCS layer (such as Git or Subversion), it exposes systems to immediate command execution. An attacker who injects command options prefixed with hyphens into the repository source URLs can force local command line tools to execute arbitrary processes. The combined vulnerability vectors represent a critical threat to developmental pipelines and software supply chain integrity.
Remediation requires immediate upgrade of Composer installations to the non-vulnerable versions released by the maintainers. For environments leveraging the standard v2.x release track, administrators must upgrade to version 2.10.2 or later. If the infrastructure relies on the legacy long-term support branch, installations must be updated to version 2.2.29 or newer.
To perform the upgrade, administrators can leverage the built-in self-update utility by executing composer self-update --stable. For containerized build pipelines, Docker files must be modified to fetch the specified secure releases during the build stage. It is recommended to automate these version updates to prevent the regression of dependency management components.
As a supplementary defense-in-depth practice, developers should limit the configuration of custom package repositories in composer.json and avoid referencing untrusted sources. Running Composer within isolated container environments with restricted file system permissions minimizes the damage an arbitrary file write can cause. Additionally, integrating the composer audit check inside continuous deployment pipelines helps identify and isolate outdated dependencies before resolution occurs.
CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Composer Composer | >= 1.0, < 2.2.29 | 2.2.29 |
Composer Composer | >= 2.3.0, < 2.10.2 | 2.10.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 (Path Traversal), CWE-787 (Out-of-bounds Write) |
| Attack Vector | Local (Requires user interaction to run Composer commands) |
| CVSS Score | 7.0 (High) |
| EPSS Score | 0.00132 (Percentile: 3.13%) |
| Impact | Arbitrary File Write, Remote Code Execution (RCE) via path traversal |
| Exploit Status | Proof-of-Concept via unit tests, no active exploitation |
| KEV Status | Not Listed |
The software uses external input to construct a pathname that is intended to be within a restricted directory, but it does not properly neutralize special elements within the pathname.
A heap out-of-bounds write vulnerability exists in Pillow prior to version 12.3.0 due to an integer overflow during image expansion calculations. The subsequent patch introduced a division-by-zero regression causing denial of service.
CVE-2026-59198 is a high-severity heap out-of-bounds read vulnerability in Pillow, the Python imaging library, affecting versions from 5.2.0 up to 12.3.0. The vulnerability occurs in the TGA RLE compression path due to a calculation mismatch between the allocated packed 1-bit row buffer and the byte-level pixel stride assumption in the C-level encoder. This mismatch allows an attacker to leak up to approximately 57 KB of adjacent process heap memory directly into generated TGA image files.
A critical signed 32-bit integer overflow vulnerability was identified in Pillow (Python Imaging Library) versions prior to 12.3.0. The vulnerability resides within the native C extension library (libImaging) during coordinate and bounding box calculations in functions like ImagingPaste and ImagingFill2. Exploitation can bypass bounds and clipping safety checks, leading to a controlled heap backward underwrite and application crash.
CVE-2026-59200 is a high-severity uncontrolled resource consumption vulnerability in the Pillow Python Imaging Library. The flaw resides in the PDF stream decoder, allowing remote, unauthenticated attackers to trigger host out-of-memory crashes by submitting malicious PDF decompression bombs.
A denial-of-service (DoS) vulnerability in Pillow (Python Imaging Library) versions 12.0.0 through 12.2.0 allows unauthenticated remote attackers to trigger 100% CPU utilization and hang the processing thread. The issue occurs within the Encapsulated PostScript (EPS) image parser (PIL/EpsImagePlugin.py) due to missing validation on the byte count parsed from %%BeginBinary: comments, allowing negative values to cause an infinite backward stream seek loop. This formatting-level state-looping issue occurs during the initial format sniffing phase inside Image.open() and does not require the system Ghostscript interpreter to be executed or present. It is resolved in version 12.3.0.
A Denial of Service vulnerability exists in the JPEG2000 decoder of Pillow (versions 8.2.0 to 12.2.0) due to memory allocation state accumulation across tiles, leading to rapid process termination.