CWE-78CriticalMITRE entry

OS Command Injection

Improper Neutralization of Special Elements used in an OS Command (OS Command Injection)

What it is

CWE-78 exists when an application passes user-controlled data to a system shell or external process without proper neutralization. The attacker injects shell metacharacters (;, &&, |, backticks) that cause the operating system to execute additional commands beyond the intended one.

Why it matters

OS command injection often grants remote code execution as the application's service account. In container deployments, this typically means escape paths into the container's tooling and credentials. In serverless or Lambda-style environments, it can leak ephemeral IAM credentials. Command injection is consistently in the CWE Top 25 and is responsible for some of the most consequential breaches in the historical record.

Common patterns

  • child_process.exec or os.system called with a string built from user input.
  • Image, video, or document processing pipelines that shell out to ImageMagick, ffmpeg, or LibreOffice with filenames from uploads.
  • Git commands constructed from user-controlled branch or repo names.
  • DNS, network, or system-info CLIs called from web admin panels (ping, nslookup, whois).
  • Backup or restore scripts triggered from web UIs.

Languages affected

PythonJavaScriptTypeScriptRubyGoJavaPHPShell

What Deva detects

Deva's taint-mode rules track input sources to shell-exec sinks across Node (child_process.exec, execSync, spawn with shell:true), Python (os.system, subprocess with shell=True, os.popen), Ruby (Kernel#`, system, exec), Go (exec.Command via sh -c), and Java (Runtime.getRuntime().exec). The scanner distinguishes safe array-style invocations (which do not invoke a shell) from string-style invocations (which do).

Example

Vulnerable

const { exec } = require('child_process')

app.get('/ping', (req, res) => {
  exec(`ping -c 1 ${req.query.host}`, (err, stdout) => {
    res.send(stdout)
  })
})

Fixed

const { execFile } = require('child_process')

app.get('/ping', (req, res) => {
  if (!/^[a-zA-Z0-9.-]+$/.test(req.query.host)) {
    return res.status(400).send('Invalid host')
  }
  execFile('ping', ['-c', '1', req.query.host], (err, stdout) => {
    res.send(stdout)
  })
})

Explanation

The vulnerable version uses exec with a shell-interpreted string. An attacker passing ?host=8.8.8.8;cat /etc/passwd executes both commands. The fix uses execFile with an argument array (no shell), and validates the host against an allowlist character set. Array-style argument passing means shell metacharacters in user input are treated as literal text, not parsed as syntax.

Where this fits in OWASP Top 10

Compliance framework mapping

FrameworkControls
OWASP Top 10 (2021)
A03:2021 Injection
NIST 800-53 Rev 5
SI-10 Information Input ValidationSI-11 Error Handling
PCI-DSS v4.0
6.2.4 Software engineering techniques
CMMC 2.0 L2
SI.L2-3.14.1 Flaw remediation

Related CWEs

Deva detects CWE-78 alongside 970+ other CWE patterns at write time, with AI-assisted fix generation that maintains compliance.