Security

What is Argument Injection (CWE-88)?

Argument Injection (CWE-88) lets attackers inject extra command-line flags. See real vulnerable/secure code and the argument-array fix.

SP
Shreya Pillai July 27, 2026 6 min read Security
AI-friendly summary

What it is: Argument Injection (CWE-88) is a type of injection vulnerability where an application constructs a command string but does not properly delimit the intended arguments, letting an attacker inject extra flags or switches.

Why it matters: Even argument-array execution (which prevents full OS Command Injection) doesn't automatically stop this — a user-controlled value that becomes one argument can still be crafted as a flag the target command wasn't meant to receive.

How to fix it: Validate that user-supplied arguments don't start with a flag character, or use the "--" separator convention to mark the end of flag parsing.

TL;DR: Argument Injection lets an attacker inject extra command-line flags into a fixed command by controlling one of its arguments; the fix is validating against leading dashes or using a “–” separator, on top of (not instead of) argument-array execution.

Field Value
CWE ID CWE-88
OWASP Category A05:2025 - Injection
CAPEC CAPEC-137, CAPEC-174, CAPEC-41, CAPEC-460, CAPEC-88
Typical Severity High
Affected Technologies Any language that invokes external commands with arguments
Detection Difficulty Moderate
Last Updated 2026-07-27

What is Argument Injection?

Improper Neutralization of Argument Delimiters in a Command (‘Argument Injection’) (CWE-88) is a type of injection vulnerability that occurs when a product constructs a string for a command to be executed by a separate component, but does not properly delimit the intended arguments, options, or switches within that command string. As defined by the MITRE Corporation under CWE-88, and classified by the OWASP Foundation under A05:2025 - Injection, this weakness is a direct child of the broader Command Injection weakness (CWE-77).

Quick Summary

Argument Injection is the attack that survives the fix for OS Command Injection. Switching from os.system() to an argument-array API like subprocess.run([...]) closes off the shell-metacharacter attack entirely — but if one of the array’s elements is still built from unvalidated user input, an attacker can make that single argument look like a flag (--output=/etc/passwd) instead of the plain value the developer expected, and the target program will happily parse it that way.

Jump to: Quick Summary · Argument Injection Overview · How Argument Injection Works · Business Impact of Argument Injection · Argument Injection Attack Scenario · How to Detect Argument Injection · How to Fix Argument Injection · Framework-Specific Fixes for Argument Injection · How to Ask AI to Check Your Code for Argument Injection · Argument Injection Best Practices Checklist · Argument Injection FAQ · Vulnerabilities Related to Argument Injection · References · Scan Your Own Site

Argument Injection Overview

What: A user-controlled value becomes a command-line argument without validating whether it looks like a flag rather than a plain value.

Why it matters: This bypasses the protection that argument-array execution provides against full OS Command Injection, since no shell parsing is needed for this attack.

Where it occurs: Any feature that passes a user-controlled value as one argument to an external command, even via a safe argument-array API.

Who is affected: Applications that pass unvalidated user input as command arguments, regardless of whether they use shell strings or argument arrays.

Who is NOT affected: Applications that validate arguments against leading flag characters, or that use a “–” separator before any user-controlled positional argument.

How Argument Injection Works

Root Cause

A user-controlled value becomes a single command-line argument without validating whether it could be interpreted as a flag or switch by the target command.

Attack Flow

  1. The attacker identifies a feature where user input becomes one argument to an external command (even via a safe argument-array API).
  2. The attacker submits a value starting with a flag-indicating character, e.g. --output=/var/www/shell.php.
  3. The application passes this value as an argument to the command, with no shell involved at all.
  4. The target command’s own argument parser interprets the value as a flag, not the plain data the developer expected.
  5. The attacker achieves altered command behavior — potentially writing a file, changing an output destination, or enabling a dangerous option.

Prerequisites to Exploit

  • User input becomes a single argument to an external command.
  • The target command’s own argument parser treats a leading dash/double-dash as a flag indicator.
  • The application does not validate the argument against this pattern or use a -- separator.

Vulnerable Code

import subprocess

def convert_image(input_path, output_name):
    subprocess.run(["convert", input_path, output_name])

output_name is passed as a plain positional argument with no validation, so a value like --write=/var/www/html/shell.php is parsed by convert as a flag rather than a filename, potentially letting the attacker control where output is written.

Secure Code

import subprocess

def convert_image(input_path, output_name):
    if output_name.startswith("-"):
        raise ValueError("Invalid output name")
    subprocess.run(["convert", "--", input_path, output_name])

The value is explicitly rejected if it starts with a dash, and the -- separator additionally tells convert that everything after it is a positional argument, never a flag, regardless of its leading characters.

Business Impact of Argument Injection

Confidentiality: Attackers may use injected flags to read data the command wasn’t meant to expose (e.g. a “read config from” flag pointed at a sensitive file).

Integrity: Attackers may use injected flags to write or overwrite files via an “output to” or similar flag.

Availability: Attackers may use injected flags to alter execution logic in ways that crash or disrupt the target command.

  • Altered execution logic of a trusted, already-fixed command via unexpected flags
  • Potential remote code execution if the injected flag allows writing an executable file to a web-servable location

Argument Injection Attack Scenario

  1. An attacker finds an image-conversion feature that passes a user-supplied output filename as a command argument.
  2. They submit --write=/var/www/html/shell.php instead of a plain filename.
  3. The image-conversion tool’s own argument parser interprets this as a flag telling it to write output to that path.
  4. The attacker retrieves the written file via the web server, achieving remote code execution.

How to Detect Argument Injection

Manual Testing

  • Identify every place user input becomes a single argument to an external command.
  • Submit values starting with - or -- to see whether the target command’s behavior changes unexpectedly.
  • Confirm whether a -- separator or leading-dash validation is in place before user-controlled arguments.

Automated Scanners (SAST / DAST)

Static analysis can flag command invocations where a user-controlled value becomes an argument without a leading-dash check, while dynamic testing with flag-like payloads confirms whether the live application’s target command actually changes behavior.

PenScan Detection

PenScan’s scanner engines test inputs that become command arguments with flag-like payloads to confirm whether the target command’s behavior changes.

False Positive Guidance

If the application validates every user-controlled argument against a leading-dash pattern or uses a -- separator consistently, a flag-like test payload should be rejected or treated as literal data — confirm the actual command’s observed behavior before treating a passed test as a real finding.

How to Fix Argument Injection

  • Validate that user-supplied arguments don’t start with - or -- before passing them to a command.
  • Use the -- separator convention (supported by most POSIX-style CLI tools) to mark the end of flag parsing before user-controlled positional arguments.
  • Combine this with argument-array execution (never shell strings) as defense-in-depth against both Argument Injection and full OS Command Injection.

Framework-Specific Fixes for Argument Injection

  • Python: validate arguments against a leading-dash pattern and use a -- separator with subprocess.run(), as shown above.
  • Java: validate each ProcessBuilder argument against a leading-dash pattern before adding it to the argument list.
  • Node.js: validate arguments before passing them to execFile()/spawn(), and use a -- separator if the target command supports it.
  • PHP: validate arguments before passing them to proc_open(), and use escapeshellarg() alongside a -- separator where the target command supports it.

How to Ask AI to Check Your Code for Argument Injection

Copy-paste prompt

Review the following [language] code block for potential CWE-88 Argument Injection vulnerabilities and rewrite it to validate against leading-dash flag characters and use a "--" separator before user-controlled arguments: [paste code here]

Argument Injection Best Practices Checklist

✅ Validate user-supplied arguments against leading dash/double-dash characters ✅ Use a “–” separator before user-controlled positional arguments where supported ✅ Combine with argument-array execution as defense-in-depth ✅ Test argument-position inputs with flag-like payloads during review

Argument Injection FAQ

How does Argument Injection differ from OS Command Injection?

OS Command Injection (CWE-78) lets an attacker run an entirely new, separate command via shell metacharacters; Argument Injection instead manipulates the arguments/flags passed to a single, already-fixed command, changing its behavior without ever invoking a new one.

How can an injected argument change what a command does?

Many command-line tools treat a leading “-“ or “–” as the start of a flag rather than a plain value, so if user input reaches an argument position unescaped, an attacker can inject flags like “–output” or “-exec” that the tool wasn’t meant to receive from that input.

How does argument-array execution alone not fully prevent this?

Argument-array execution (bypassing the shell) prevents OS Command Injection, but if a single user-controlled value still becomes one argument in that array, an attacker can still inject a flag-like value into that specific argument slot unless it’s validated.

How do I detect Argument Injection in my own application?

Identify where user input becomes a single argument to an external command, and test submitting values starting with “-“ or “–” to see whether the target command’s behavior changes unexpectedly.

How do I fix Argument Injection correctly?

Validate that user-supplied arguments don’t start with a flag-indicating character, or use a “–” separator (supported by many CLI tools) to explicitly mark the end of flag parsing before positional arguments begin.

How does the “–” separator convention help specifically?

Many command-line tools follow the POSIX convention that everything after a bare “–” argument is treated as a positional value, never as a flag, so placing it before user-controlled arguments closes off flag injection even if the value happens to start with a dash.

How can PenScan help find Argument Injection?

PenScan tests inputs that become command arguments with flag-like payloads (values starting with “-“ or “–”) to confirm whether the target command’s behavior changes.

CWE Name Relationship
CWE-77 Improper Neutralization of Special Elements used in a Command (‘Command Injection’) ChildOf
CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component (‘Injection’) ChildOf

References

Scan Your Own Site

Manual code review catches what you know to look for. An automated scan catches what you didn’t. Scan your own website using PenScan to find Argument Injection and other risks before an attacker does.