VAITP Dataset

← Back to the dataset

CVE-2026-42563

Command injection in Dulwich's merge driver via crafted file paths.

  • CVSS 7.7
  • CWE-78
  • Input Validation and Sanitization
  • Remote

Dulwich is a pure-Python implementation of the Git file formats and protocols. Starting in version 0.24.0 and prior to version 1.2.5, Dulwich's `ProcessMergeDriver` substitutes the file path (from the git tree, controllable by an attacker via a malicious branch) into the merge driver command via the `%P` placeholder and executes it with `subprocess.run(…, shell=True)`. An attacker who can cause a victim to merge an untrusted branch can achieve arbitrary command execution by crafting malicious file paths. Version 1.2.5 fixes the issue.

CVSS base score
7.7
Published
2026-06-10
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Command Injection
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
Dulwich
Fixed by upgrading
Yes

Solution

Upgrade Dulwich to version 1.2.5 or later.

Vulnerable code sample

import subprocess

class ProcessMergeDriver(object):

    def __init__(self, command):
        self.command = command

    def merge(self, path, base_contents, local_contents, remote_contents):
        cmd = self.command.replace('%P', path)
        # Note: In the actual library, other placeholders like %A, %O, %B
        # for temporary file paths would also be substituted here.

        # The vulnerability is executing the command with shell=True, allowing
        # a malicious file path to be interpreted by the shell.
        proc = subprocess.run(
            cmd,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)

        if proc.returncode == 0:
            return proc.stdout
        else:
            # Handle merge failure
            return None

Patched code sample

import subprocess
import shlex

def run_fixed_merge_driver(driver_command_template, file_path):
    """
    Demonstrates the fixed approach to running a merge driver, which avoids
    shell injection vulnerabilities (like CVE-2026-42563).

    The fix involves two key changes from the vulnerable implementation:
    1. The command string is tokenized into a list using `shlex.split()`.
    2. `subprocess.run()` is called with this list, and `shell=True` is NOT used.
       (The default `shell=False` is the secure option).

    This ensures that the `file_path`, even if it contains shell metacharacters,
    is treated as a single, literal argument to the command, rather than being
    interpreted by the shell.
    """
    # 1. Split the command template into a list of arguments.
    command_list = shlex.split(driver_command_template)

    # 2. Safely substitute the placeholder with the file path.
    # Each item in the list is processed, so the path becomes one argument.
    final_command = [arg.replace('%P', file_path) for arg in command_list]

    print(f"Attempting to execute with safe method: {final_command}")

    # 3. Execute the command using the list of arguments.
    # shell=False is the default and is secure. The OS handles the arguments
    # safely, preventing the injection from being executed.
    # We use 'echo' to safely demonstrate the principle.
    try:
        result = subprocess.run(final_command, check=True, capture_output=True, text=True)
        print("--- Execution Output ---")
        print(result.stdout.strip())
        print("------------------------")
        print("Success: The command executed, but the malicious payload was not interpreted by the shell.")
        print("The injected command was treated as a literal string argument.")
    except (FileNotFoundError, subprocess.CalledProcessError) as e:
        print(f"Execution failed as expected or command not found: {e}")


if __name__ == '__main__':
    # The merge driver command template, as might be configured in Git.
    # We use 'echo' as a safe, illustrative command.
    driver = "echo File path is %P"

    # A malicious file path crafted by an attacker.
    # The intent is to inject the 'id' command.
    malicious_path = "harmless_name.txt; id"

    print("--- Demonstrating the fix for CVE-2026-42563 ---")
    run_fixed_merge_driver(driver, malicious_path)

Payload

$(touch /tmp/pwned)

Cite this entry

@misc{vaitp:cve202642563,
  title        = {{Command injection in Dulwich's merge driver via crafted file paths.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-42563},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-42563/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::