Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59948

CVE-2026-59948: Composer Path Traversal Vulnerability

CVE-2026-59948 is a path traversal vulnerability in Composer that allows attackers to write malicious files outside the vendor directory. This article covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-59948 Overview

CVE-2026-59948 is a path traversal vulnerability [CWE-22] in Composer, the dependency manager for PHP. A maliciously crafted package served from an untrusted repository can cause Composer to write attacker-controlled files outside the vendor directory and outside the project root during install or update operations. The flaw exists because invalid package names are not correctly validated before dependency-resolution results are written or installed. The issue affects Composer versions prior to 2.2.29 and 2.10.2. Packages served from Packagist.org or Private Packagist are not affected.

Critical Impact

An untrusted Composer repository can drop attacker-controlled files anywhere the running user has write access, enabling arbitrary file writes that can escalate to code execution.

Affected Products

  • Composer versions prior to 2.2.29 (2.2.x branch)
  • Composer versions prior to 2.10.2 (2.x branch)
  • PHP projects consuming packages from untrusted third-party Composer repositories

Discovery Timeline

Technical Details for CVE-2026-59948

Vulnerability Analysis

Composer resolves dependencies and then writes lock data and installs package files based on metadata received from a configured repository. The vulnerable code path in src/Composer/DependencyResolver/LockTransaction.php accepts package names from repository responses without applying the strict validation used elsewhere in the loader pipeline. When a package name contains path traversal sequences such as ../, Composer uses that string to construct file system paths for the lock output and install target. The result is that files are written outside the intended vendor/ directory and outside the project root during normal composer install or composer update runs.

Exploitation requires that the victim adds and trusts a malicious repository entry in composer.json (for example a custom type: composer or type: vcs repository) and then runs an install or update. Packagist.org and Private Packagist perform independent package name validation and are not usable as attack vectors.

Root Cause

The root cause is missing use of the ValidatingArrayLoader package-name validation before lock transaction writes. Package names should be constrained to the documented Composer pattern (vendor/name with a limited character set), but the affected code path treated the repository-supplied name as trusted input when computing install destinations.

Attack Vector

The attack requires user interaction to add a hostile repository and to run Composer, and it executes with local file system privileges of the invoking user. A malicious repository returns a package definition with a crafted name such as vendor/../../../../etc/cron.d/pwn, and Composer resolves and installs it, writing attacker-controlled content to that path.

php
// Security patch: import ValidatingArrayLoader in LockTransaction
// Source: https://github.com/composer/composer/commit/502c6c4f699802d9cf464728b3e8a95674f919a0

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
+use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Package\Package;
use Composer\Pcre\Preg;
php
// New SecurityException class introduced by the fix
// Source: https://github.com/composer/composer/commit/502c6c4f699802d9cf464728b3e8a95674f919a0

<?php declare(strict_types=1);

namespace Composer\Exception;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SecurityException extends \UnexpectedValueException
{
}

Detection Methods for CVE-2026-59948

Indicators of Compromise

  • Files created outside the vendor/ directory or outside the project root shortly after a composer install or composer update execution.
  • composer.json entries referencing third-party repositories blocks pointing at unverified hosts.
  • Package names in composer.lock containing traversal sequences (../, ..\\, absolute paths) or characters outside [a-z0-9_.-]/[a-z0-9_.-].
  • Unexpected new or modified files in sensitive paths such as /etc/cron.d/, ~/.ssh/, or web-writable directories on developer or CI hosts.

Detection Strategies

  • Audit composer.json and composer.lock files across repositories for non-Packagist repository declarations and validate the referenced hosts.
  • Static-scan lock files with a regular expression that rejects any package name not matching ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.-]?|-{0,2})[a-z0-9]+)*$.
  • Enable file integrity monitoring on developer workstations and CI runners for writes outside declared project trees during Composer runs.
  • Correlate CI pipeline logs of composer install with file creation events on protected paths.

Monitoring Recommendations

  • Log the exit output of Composer in CI and grep for unusual install target paths written to disk.
  • Alert on process launches of composer where the parent CI job also generates file writes outside ${CI_PROJECT_DIR}.
  • Track the installed Composer version across build agents and flag any host running a version below 2.2.29 or 2.10.2.

How to Mitigate CVE-2026-59948

Immediate Actions Required

  • Upgrade Composer to 2.10.2 on the current branch or 2.2.29 on the legacy 2.2 LTS branch immediately on all developer machines, build agents, and container images.
  • Inventory all composer.json files and remove or replace untrusted repositories entries; prefer Packagist.org or Private Packagist.
  • Rotate credentials and review file system state on any host that ran composer install or composer update against an untrusted repository.

Patch Information

The fix is available in Composer 2.10.2 and Composer 2.2.29. The patch introduces a SecurityException class and routes package names through ValidatingArrayLoader before lock-transaction writes, rejecting names that do not match the Composer naming specification. See the commits 502c6c4 and c50b1ef for the code changes.

Workarounds

  • Restrict Composer package sources to Packagist.org or Private Packagist until upgrade is possible.
  • Run composer install and composer update inside isolated containers or unprivileged sandboxes so that traversal writes cannot reach sensitive host paths.
  • Enforce code review on any pull request that modifies the repositories section of composer.json.
bash
# Upgrade Composer to a patched release
composer self-update 2.10.2
# Legacy 2.2 LTS branch
composer self-update --2.2 2.2.29

# Verify installed version
composer --version

# Audit lock files for suspicious package names
grep -RInE '"name"\s*:\s*"[^"]*(\.\./|\\\\)' ./**/composer.lock

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.