Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')

Description

Improper Neutralization of Argument Delimiters in a Command, commonly known as Argument Injection, occurs when software constructs a command string using input from an upstream component but fails to properly neutralize special characters that can modify how arguments are parsed. Unlike command injection which introduces entirely new commands, argument injection manipulates the arguments passed to an existing command, potentially changing its behavior in unintended ways. Attackers can inject additional arguments, override existing flags, specify malicious file paths, or alter command behavior by exploiting how shells and programs parse argument delimiters such as spaces, quotes, hyphens, and equals signs.

Risk

Argument injection can be as dangerous as full command injection depending on the target command's capabilities. Many system utilities accept powerful arguments: curl can upload files, tar can overwrite arbitrary files, find can execute commands, and git can run arbitrary scripts through hooks. Attackers can leverage these capabilities by injecting arguments even when the base command is fixed. The vulnerability is often overlooked because developers focus on preventing shell metacharacters while ignoring that argument parsing itself can be exploited. Filename-based attacks are particularly effective: a file named --help or -rf can cause unexpected behavior when passed to commands.

Solution

Pass arguments as separate array elements rather than constructing command strings. Use APIs that accept argument arrays (e.g., Python's subprocess with list arguments, PHP's proc_open with arguments array). When constructing argument strings is unavoidable, validate that input matches expected patterns using strict allowlists. For filenames, prefix user-controlled paths with ./ to prevent interpretation as arguments (e.g., ./--filename). Escape or reject inputs containing characters that could be interpreted as argument delimiters or flag indicators. Consider whether the command being called has dangerous options and restrict input accordingly.

Common Consequences

ImpactDetails
ConfidentialityScope: Confidentiality

Injected arguments can cause commands to output sensitive information, read arbitrary files, or transmit data to attacker-controlled destinations.
IntegrityScope: Integrity

Arguments can direct commands to write, modify, or delete files, change configurations, or alter system state in unintended ways.
AvailabilityScope: Availability

Malicious arguments can cause commands to consume excessive resources, run indefinitely, or corrupt critical data.
Access ControlScope: Access Control

Some commands accept arguments that execute additional code or scripts, enabling privilege escalation or unauthorized access.

Example Code + Solution Code

Vulnerable Code

import subprocess
import os

# VULNERABLE: User input in argument string
def compress_file(filename):
    # Attacker input: "--help" or "-rf /etc" or "; rm -rf /"
    command = f"tar -czf backup.tar.gz {filename}"
    os.system(command)

# VULNERABLE: Filename can be interpreted as argument
def list_file(user_filename):
    # If filename is "--help", tar shows help instead of error
    # If filename is "-rf", it could be dangerous
    subprocess.run(f"ls {user_filename}", shell=True)

# VULNERABLE: Git with user-controlled branch name
def checkout_branch(branch):
    # Attacker: "--upload-pack=malicious_script"
    subprocess.run(f"git fetch origin {branch}", shell=True)

Fixed Code

import subprocess
import re
import shlex

# SAFE: Arguments as list elements, not string
def compress_file(filename):
    # Validate filename format
    if not re.match(r'^[\w\-./]+$', filename):
        raise ValueError("Invalid filename")

    # Prefix with ./ to prevent argument interpretation
    safe_filename = f"./{filename}" if not filename.startswith('/') else filename

    # Use argument list - no shell interpretation
    subprocess.run(
        ['tar', '-czf', 'backup.tar.gz', safe_filename],
        check=True
    )

# SAFE: Argument array prevents injection
def list_file(user_filename):
    # Validate and sanitize
    if not user_filename or '..' in user_filename:
        raise ValueError("Invalid filename")

    # Use -- to signal end of options
    subprocess.run(['ls', '--', user_filename], check=True)

# SAFE: Strict allowlist validation
def checkout_branch(branch):
    # Only allow valid branch name characters
    if not re.match(r'^[a-zA-Z0-9_\-/]+$', branch):
        raise ValueError("Invalid branch name")

    if branch.startswith('-'):
        raise ValueError("Branch name cannot start with dash")

    subprocess.run(['git', 'fetch', 'origin', branch], check=True)

# SAFE: Using -- argument separator
def safe_command_with_filename(filename):
    # The -- signals end of options for many Unix commands
    subprocess.run(['rm', '--', filename], check=True)

Exploited in the Wild

Git Argument Injection Attacks (Various, 2017-Present)

Multiple Git-related argument injection vulnerabilities have been discovered and exploited. CVE-2017-1000117 allowed attackers to inject arguments through malicious repository URLs, executing arbitrary code via git hooks. Similar vulnerabilities in git submodule handling enabled code execution through crafted repository configurations.

Mercurial HG Argument Injection (Mercurial, 2017)

CVE-2017-9462 allowed argument injection in Mercurial's hg serve command, enabling remote code execution through specially crafted repository names that injected malicious arguments.


Tools to test/exploit

  • Commix — command injection tool that includes argument injection payload testing capabilities.

  • Custom Wordlists — argument injection payloads for various commands and contexts.


CVE Examples

  • CVE-2017-1000117 — Git arbitrary code execution via malicious SSH URLs with argument injection.

  • CVE-2022-24765 — Git for Windows argument injection allowing arbitrary command execution.

  • CVE-2023-29007 — Git symbolic ref argument injection leading to arbitrary file read.


References

  1. MITRE. "CWE-88: Improper Neutralization of Argument Delimiters in a Command." https://cwe.mitre.org/data/definitions/88.html

  2. OWASP. "OS Command Injection Defense Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html