Skip to content
Pro Analyzer — Available with ShieldCI Pro

Command Injection Analyzer

Analyzer IDCategorySeverityTime To Fix
command-injection🛡️ SecurityCritical30 minutes

What This Checks

This analyzer detects command injection vulnerabilities in your Laravel application by identifying unsafe shell execution patterns where user input can be exploited to execute arbitrary system commands.

Detected Vulnerable Patterns:

Shell Execution Functions (7)

  • system() - Executes command and outputs result
  • exec() - Executes command and returns last line
  • passthru() - Executes command and passes output directly
  • shell_exec() - Executes command via shell and returns output
  • popen() - Opens a process file pointer
  • proc_open() - Executes command with full I/O control
  • pcntl_exec() - Replaces current process with command

Shell Operators (1)

  • Backtick operator (`cmd`) - Executes shell command (often overlooked!)

Laravel APIs

  • Process facade: Process::run(), ::command(), ::pipe(), ::pool(), ::start() with string commands
  • process() helper (Laravel 10+): process($cmd) with a string command
  • Artisan facade: Artisan::call() / ::queue() - Critical if command name is user-controlled, Medium if only parameters are

Symfony Process Component

  • new Process($cmd) instantiated with a string command

What's NOT Flagged

The analyzer correctly recognizes these as safe:

  • Static string literals: system('php artisan config:cache')
  • Properly escaped input: system(escapeshellarg($request->input('file')))
  • All arguments escaped: $file = escapeshellarg($input); system($file);
  • No user input: exec('composer dump-autoload')

Why It Matters

Command injection is a critical security vulnerability (OWASP Top 10) that allows attackers to execute arbitrary operating system commands on your server, leading to:

  • Remote Code Execution (RCE) - Complete server compromise
  • Data Exfiltration - Stealing sensitive files, databases, environment variables
  • System Manipulation - Creating backdoors, deleting files, installing malware
  • Lateral Movement - Using compromised server to attack other systems
  • Denial of Service - Crashing services or consuming resources

A single command injection vulnerability can give attackers complete control of your server, making it one of the most dangerous security issues.

How to Fix

Quick Fix (5 minutes)

Use escapeshellarg() or escapeshellcmd() to escape user input:

Before (❌):

php
public function processFile(Request $request)
{
    $filename = $request->input('file');

    // VULNERABLE: User input passed directly to shell
    system("cat {$filename}");
}

After (✅):

php
public function processFile(Request $request)
{
    $filename = $request->input('file');

    // SAFE: User input properly escaped
    $escaped = escapeshellarg($filename);
    system("cat {$escaped}");
}

Proper Fix (30 minutes)

Avoid shell execution entirely - Use PHP native functions:

Before (❌):

php
public function listFiles(Request $request)
{
    $directory = $request->input('dir');

    // VULNERABLE: Using shell to list files
    $output = shell_exec("ls -la {$directory}");
    return response()->json(['files' => $output]);
}

After (✅):

php
public function listFiles(Request $request)
{
    $directory = $request->input('dir');

    // SAFE: Using PHP native functions
    $validated = realpath($directory);

    if (!$validated || !is_dir($validated)) {
        abort(400, 'Invalid directory');
    }

    $files = scandir($validated);
    return response()->json(['files' => $files]);
}

Best Practice for Process Execution (✅✅):

When shell execution is unavoidable, use Symfony Process with array arguments:

Before (❌):

php
use Symfony\Component\Process\Process;

public function deploy(Request $request)
{
    $branch = $request->input('branch');

    // VULNERABLE: String command with interpolation
    $process = Process::fromShellCommandline("git pull origin {$branch}");
    $process->run();
}

After (✅):

php
use Symfony\Component\Process\Process;

public function deploy(Request $request)
{
    // Validate input first
    $validated = $request->validate([
        'branch' => 'required|alpha_dash|max:50',
    ]);

    // SAFE: Array arguments prevent shell interpretation
    $process = new Process([
        'git',
        'pull',
        'origin',
        $validated['branch']
    ]);

    $process->run();

    if (!$process->isSuccessful()) {
        throw new ProcessFailedException($process);
    }
}

References