← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

escapeshellarg()

php PHP 5.0+ Intermediate
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep, psalm, and phpstan — all specialist SAST/static-analysis tools that can detect variable interpolation in shell calls without escapeshellarg. This is not caught by the compiler or default linter, but these tools do identify the pattern.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes wrapping each argument with escapeshellarg() — a small, localised change per shell call. However, common_mistakes note that every user-controlled argument must be addressed and the command name itself may also need whitelisting, making it slightly more than a single-line swap but still contained within one component.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to contexts are web and cli, but the concern is localised to the specific code paths that invoke shell commands. It doesn't impose a codebase-wide structural tax — only the portions of code calling shell functions are affected.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states directly that developers believe escapeshellarg() makes any shell command safe, but it only protects arguments — user input in the command name itself remains dangerous. The common_mistakes also note confusion with escapeshellcmd(). This contradicts intuitive expectations and mirrors how similar escaping functions work in other contexts, earning a t7.

About DEBT scoring →

Also Known As

escapeshellarg() shell argument escaping shell safe argument

TL;DR

Wraps a string in single quotes and escapes internal quotes for safe use as a single shell argument.

Explanation

escapeshellarg($arg) wraps the value in single quotes and escapes any single quotes within, producing a shell-safe single argument. This prevents the argument from being interpreted as multiple arguments or from injecting shell metacharacters (;, |, &, $, etc.). It must be used on every individual argument passed to exec(), system(), shell_exec(), or passthru(). Note: even with escaping, allowing user input in shell commands is high-risk — whitelist known-good values where possible.

Common Misconception

escapeshellarg() makes any shell command safe. It safely wraps an argument in quotes but does nothing if user input appears in the command name itself rather than its arguments. When possible, use proc_open() with an array to avoid the shell entirely.

Why It Matters

escapeshellarg() wraps a value in single quotes and escapes internal quotes, safely turning user input into a shell argument — without it, shell metacharacters execute arbitrary commands.

Common Mistakes

  • Using escapeshellarg() on the entire command string instead of individual arguments — the function is for arguments, not commands.
  • Not applying escapeshellarg() to every user-controlled value in a shell call, missing one.
  • Using escapeshellcmd() instead — it escapes shell metacharacters but still allows argument injection.
  • Not considering that even escapeshellarg() cannot make a user-controlled command name safe — validate the command from a whitelist.

Code Examples

✗ Vulnerable
// Missing escapeshellarg — command injection:
$filename = $_GET['file'];
exec("convert $filename output.png"); // ?file=x;cat /etc/passwd

// Safe:
exec('convert ' . escapeshellarg($filename) . ' output.png');
✓ Fixed
// Wraps value in single quotes and escapes internal quotes
\$file   = escapeshellarg(\$_POST['filename']);
\$output = shell_exec('file ' . \$file); // safe argument

// escapeshellcmd() escapes the command itself (less common)
\$cmd = escapeshellcmd('convert');
exec(\$cmd . ' ' . escapeshellarg(\$src) . ' ' . escapeshellarg(\$dst));

// Best: proc_open with array — no shell involved at all
\$process = proc_open(
    ['convert', \$src, \$dst], // array = no shell expansion
    [0 => ['pipe','r'], 1 => ['pipe','w'], 2 => ['pipe','w']],
    \$pipes
);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 1 ping S 1 ping M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 8 Ahrefs 5 Perplexity 3 Unknown AI 2 Majestic 1 Google 1
crawler 20
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Low
⚡ Quick Fix
Use escapeshellarg() on every argument to shell commands — it wraps the argument in single quotes and escapes internal single quotes, making injection impossible
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
shell_exec exec system with variable interpolation without escapeshellarg; user input in shell command argument
Auto-detectable: ✓ Yes semgrep psalm phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-78 CWE-88

✓ schema.org compliant