Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-40176 — Differential proof-of-concept for CVE-2026-40176, demonstrating OS command injection in Composer's Perforce driver via a malicious repository URL, with automated A/B testing against affected and fixed versions. | Kitploit
Tools/GitHubGitHub/ikarolaborda/cve-2026-40176
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingCommand and ControlLearning & Education
GitHubikarolaborda/cve-2026-40176

CVE-2026-40176

Differential proof-of-concept for CVE-2026-40176, demonstrating OS command injection in Composer's Perforce driver via a malicious repository URL, with automated A/B testing against affected and fixed versions.

View Repository
143 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-40176 — Composer Perforce Driver Command Injection (Proof of Concept)

A self-contained, OOP-style PHP proof of concept that demonstrates and differentially verifies a command-injection vulnerability in Composer's Perforce repository driver.

The PoC runs the same malicious composer.json against two Composer binaries — an affected release (2.9.5) and a fixed release (2.9.6) — and proves the bug by observing a side effect (a marker file written by an injected shell command) that fires on the affected version but not on the fixed one.

⚠️ For authorized security research and defensive testing only. See Responsible Use.


Table of Contents

  • Summary
  • The Vulnerability
  • How the PoC Works
  • The Injection Payload
  • Requirements
  • Setup
  • Usage
  • Expected Output
  • Interpreting the Result
  • Project Structure
  • Design Notes
  • Limitations & Known Issues
  • Responsible Use
  • References

Summary

CVECVE-2026-40176
ComponentComposer — Perforce (perforce) repository/VCS driver
ClassOS command injection via attacker-controlled repository URL
Attack surfaceA composer.json containing a crafted repositories entry of type: perforce
AffectedComposer 2.9.5
FixedComposer 2.9.6
TriggerResolving/updating dependencies (composer update) against the malicious manifest
ImpactArbitrary command execution on the machine running Composer
PoC languagePHP (single file, no external dependencies)

The Vulnerability

Composer can resolve packages from several version-control systems. For Perforce, the repository is identified by a p4:// URL that encodes the host, port and user/stream. When Composer's Perforce driver builds the underlying p4 command line, fields taken from the attacker-controlled URL are not sufficiently sanitized before being handed to a shell.

Because the manifest author fully controls the repository URL, an attacker who can get a victim to run composer update/composer install against a malicious composer.json (for example, a poisoned dependency, a hostile repository, or a CI job processing untrusted project files) can break out of the intended p4 invocation and execute arbitrary OS commands with the privileges of the Composer process.

This belongs to the same family as historical Composer VCS-driver argument-injection issues, where URL/branch/stream values flow into shell commands without escaping. Composer 2.9.6 hardens the Perforce driver so the injected payload no longer executes.

The authoritative description of the behavior demonstrated here is the PoC source itself (CVE202640176Test.php); consult the official advisory and Composer changelog for the upstream fix details.


How the PoC Works

The PoC is a single class, CVE202640176Test, that performs a controlled A/B (differential) experiment:

  1. Preflight — queries --version on both the affected (2.9.5) and fixed (2.9.6) Composer binaries and aborts early if either cannot be invoked.
  2. Affected run (2.9.5)
    • Creates an isolated temp directory under the system temp path.
    • Writes a composer.json whose repositories section contains a perforce entry with a malicious p4:// URL carrying an injected shell payload.
    • Runs composer update in that directory.
    • Validates the result.
  3. Fixed run (2.9.6) — repeats the exact same steps against the patched binary.
  4. Restore — a finally block always restores the original composer.json in the project directory.
  5. Verdict — prints PASS only when the affected run shows the side effect and the fixed run does not.

Validation (what counts as "exploited")

For each run, validateRun() checks three things:

CheckWhat it proves
Marker file exists & contains the run IDThe injected touch/echo payload actually executed — i.e. command injection succeeded.
Composer output mentions p4The Perforce driver code path was reached (the payload was processed by the right component, not some unrelated step).
Parsed Composer version == expectedThe correct binary (2.9.5 vs 2.9.6) was the one that ran.

A run is "OK" only when all three pass. The overall test passes when the affected run is OK and the fixed run is not — the precise signature of a real vulnerability that was subsequently patched.


The Injection Payload (Explained)

The malicious repository URL is built in writeComposerJson():

p4://127.0.0.1:1666:attacker_user;touch <marker> && echo '<runId>' > <marker>:client_test

Breaking it down:

  • p4://127.0.0.1:1666:attacker_user — a well-formed-looking Perforce URL (host, port 1666, user).
  • ;touch <marker> && echo '<runId>' > <marker> — the injected shell commands. The leading ; terminates the intended p4 command; touch creates the marker file, and echo '<runId>' > <marker> writes the unique run ID into it so the PoC can confirm the payload (and not some unrelated process) produced the file.
  • :client_test — trailing text to keep the rest of the URL parsing plausible.

On the affected driver the shell metacharacters are honored and the marker file is created. On the fixed driver the value is properly escaped/quoted, so the same string is treated as inert data and no marker appears.

Note: the PoC uses a unique, timestamped run ID and writes its marker inside an isolated temp directory, so the payload is benign and self-cleaning rather than destructive.


Requirements

  • PHP 7.4+ (developed/tested against PHP 8.x CLI). The PoC itself uses only core functions — no Composer packages required to run the harness.
  • Two Composer binaries available as PHARs:
    • Composer 2.9.5 (affected)
    • Composer 2.9.6 (fixed)
  • A POSIX-like shell environment (exec() runs cd … && php …). Designed for Linux/macOS.
  • A base composer.json in the project directory (it is read at startup, copied into each temp run, and restored afterward).

You generally do not need a live Perforce server: the vulnerability is in how Composer builds the p4 command line, and the injected payload runs before/around any real p4 connection. Composer may log a Perforce connection error — that is expected and does not affect the marker-file proof.


Setup

  1. Clone / place the PoC in a working directory.

  2. Provide a composer.json in the same directory as the PoC. A minimal one is enough:

    {
      "name": "research/cve-2026-40176-poc",
      "description": "Base manifest for the CVE-2026-40176 differential PoC",
      "require": {}
    }
    
  3. Obtain the two Composer binaries and place them where the PoC expects them (defaults shown):

    /usr/local/bin/composer-2.9.5.phar   # affected
    /usr/local/bin/composer-2.9.6.phar   # fixed
    

    You can download specific Composer releases from the official archive, e.g.:

    curl -Lo /usr/local/bin/composer-2.9.5.phar https://getcomposer.org/download/2.9.5/composer.phar
    curl -Lo /usr/local/bin/composer-2.9.6.phar https://getcomposer.org/download/2.9.6/composer.phar
    

    If your paths differ, edit the two constructor arguments at the bottom of CVE202640176Test.php.


Usage

php CVE202640176Test.php

The harness runs both Composer versions in turn and prints a final verdict. The original composer.json is restored automatically even if a run fails (the work happens in throwaway temp directories).


Run in Docker (recommended)

Download Tool