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.
- CWE
- CWE-78
- 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 NonePatched 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 ::
