Injection Attacks: RCE, Command Injection & XXE

How command injection and XXE actually lead to remote code execution — and what genuinely prevents each one.

🛠️ Related tool: Open Website Security Scanner →
Command injection and XXE are two different mechanisms that both lead to the same worst-case outcome: an attacker running arbitrary code or commands on a server they were never meant to have access to. This guide covers how each actually works at a conceptual level, why they're treated as the most severe class of web vulnerability, and what genuinely stops them.

Remote Code Execution: The Outcome, Not a Single Technique

Remote Code Execution (RCE) isn't itself a specific vulnerability — it's the outcome that several different vulnerability types (command injection, XXE, insecure deserialization, certain file inclusion chains) can all lead to when successfully exploited. RCE is treated as close to the maximum-severity finding in almost any vulnerability scoring system because it typically gives an attacker the same level of control over the server that the running application process itself has — reading and modifying files, accessing databases, pivoting to other systems on the same network, or using the compromised server as a launch point for further attacks.

Understanding RCE as an outcome rather than a technique matters practically: defending against it means addressing each of the specific mechanisms that can lead to it, rather than looking for a single unified fix. Command injection and XXE, covered below, are two of the most common paths to RCE in modern web applications.

🎯
ToolsNovaHub Pro Tip
Any feature that shells out to the operating system or parses user-supplied XML is worth specifically flagging in a code review — these two categories account for a disproportionate share of RCE findings compared to how rarely they're actually needed in most applications.
⚠️
Common Beginner Mistake
Believing that escaping or sanitizing user input before passing it to a shell command is sufficient. Shell escaping is notoriously easy to get subtly wrong across different shells and platforms — avoiding shell invocation entirely is far more reliable than trying to sanitize it correctly.

Command Injection: When User Input Reaches a System Shell

Command injection happens when an application passes user-supplied input into a function that executes operating system commands, without properly separating the intended command from attacker-controlled data. Many programming languages provide convenience functions that hand a string directly to the system shell for execution — useful for legitimate tasks like running an image-conversion utility or checking network connectivity — but if any part of that string comes from user input without proper handling, an attacker can append additional shell operators (like a semicolon or pipe) to chain in entirely separate commands of their own choosing.

The canonical illustration: an application that runs a network diagnostic tool against a user-supplied hostname, building a command string like ping [hostname]. If the hostname parameter isn't properly isolated from the rest of the command, an attacker supplying a value like example.com; cat /etc/passwd causes the shell to interpret the semicolon as a command separator, running the attacker's second command immediately after the intended one. This exact pattern — a "ping" or "traceroute" style diagnostic feature — remains one of the most common real-world sources of command injection precisely because it feels like such an innocuous feature to build.

Why Command Injection Is So Persistently Common

Despite being one of the longest-known vulnerability classes in web security, command injection continues to appear in current applications for a specific, structural reason: many languages make shelling out to run a system command genuinely easy, while making it correctly and safely just as easy to get subtly wrong. Escaping shell metacharacters correctly varies by operating system and shell, is easy to overlook for edge cases, and a single missed character in an escaping function can reopen the entire vulnerability — which is why security guidance consistently recommends avoiding shell invocation entirely rather than trying to sanitize input into it safely.

The safer alternative most modern language standard libraries provide: functions that execute a specific program directly with an argument array, rather than constructing a single string interpreted by a shell. This approach means shell metacharacters in user input are never interpreted as command syntax at all, since there's no shell parsing the combined string in the first place — the input is passed as inert data to a specific program, not as part of an executable command line.

XXE: Exploiting How XML Parsers Handle External Entities

XML External Entity (XXE) injection exploits a legacy feature of the XML specification that lets a document define custom "entities" — reusable placeholders that get substituted with other content when the document is parsed, including content loaded from an external source like a local file or a URL. When an application parses XML from an untrusted source (a file upload, an API request body, a webhook payload) using a parser configured with external entity processing still enabled, an attacker can define an entity that points at a sensitive local file, and the parser will read and substitute that file's contents into the parsed output.

Beyond reading local files, a maliciously crafted XML document can define an entity that references a URL rather than a local file, causing the server to make an outbound request to an attacker-specified destination — a capability that overlaps directly with SSRF, covered in our companion guide on server-side request forgery. In more severe cases, certain parser configurations combined with specific entity structures can lead to denial of service through resource exhaustion, or in some environments, further escalation toward code execution.

Why XXE Became So Common, and Why It's Now Preventable by Default

XXE became a widespread issue specifically because external entity processing was enabled by default in most XML parser libraries for years, meaning any application parsing XML without explicitly disabling that feature was vulnerable by default rather than by mistake. Most major XML parsing libraries have since changed their default configuration to disable external entity processing, meaning applications built on current library versions with default settings are no longer automatically vulnerable — but applications built on older library versions, or ones that explicitly re-enabled the feature for some other reason, remain exposed.

This shift — from "vulnerable unless you remember to disable a feature" to "safe unless you explicitly re-enable it" — is widely regarded as one of the more successful examples of fixing a vulnerability class at the library level rather than relying on every individual application developer to remember a specific defensive step.

Command Injection vs XXE: Different Entry Points, Same Outcome Category

AspectCommand InjectionXXE
Entry pointInput passed into an OS shell commandUntrusted XML parsed with external entities enabled
Primary riskDirect command executionFile disclosure, SSRF, sometimes RCE depending on configuration
Root causeUnescaped input reaching a shell interpreterParser configuration allowing external entity resolution
Modern default risk levelStill high — shell invocation remains easy to misuseLower — most current parser libraries disable it by default
Primary fixAvoid shell invocation; use argument-array execution insteadExplicitly disable external entity processing in parser config

Insecure Deserialization: A Related Path to RCE Worth Knowing

Beyond command injection and XXE, insecure deserialization is a third common path to remote code execution worth understanding alongside them, since it shares the same underlying pattern of trusting structured data from an untrusted source more than is safe. Many programming languages support serializing objects (converting an in-memory data structure into a storable or transmittable format) and deserializing them back into live objects later. If an application deserializes data from an untrusted source without restriction, and the language's deserialization process can be made to construct objects that execute code as a side effect of being reconstructed, an attacker can craft serialized data that triggers code execution the moment it's deserialized.

This vulnerability class became widely known following several major, publicly disclosed incidents in enterprise Java and .NET applications specifically, though the underlying pattern applies to any language with a similarly flexible deserialization mechanism. The core defense mirrors XXE's: avoid deserializing data from untrusted sources at all where possible, and where unavoidable, use serialization formats and library configurations specifically designed to prevent arbitrary object construction during deserialization.

Real Scenarios Involving These Vulnerability Classes

A backup utility feature runs a system command to compress a user-specified folder name into an archive, building the command as a single string that includes the folder name directly. A security review catches that the folder-name parameter isn't isolated from the rest of the command, flagging it for conversion to argument-array execution before deployment.

An enterprise application accepts XML file uploads for a bulk-import feature, built years ago on an older parsing library version with external entity processing still enabled by default. A routine dependency audit flags the outdated library version specifically because of its default XXE exposure, prompting an upgrade that closes the gap without requiring any application code changes at all.

A penetration test against a network diagnostics dashboard finds that a "check domain availability" feature passes user input directly into a system ping command, discovered through the classic technique of testing whether shell metacharacters in the input produce any unexpected behavior — exactly the kind of finding that routine security testing is specifically designed to catch before real attackers do.

A developer troubleshoots unexpected server behavior after adding a webhook feature that parses incoming XML payloads from a third-party service, discovering the parser's default configuration in their specific library version still had external entities enabled, unlike the safer defaults in more recently updated libraries — a reminder that library defaults vary and shouldn't be assumed without checking.

Preventing Command Injection and XXE

For command injection, the single most reliable fix is avoiding shell string construction entirely: use language-standard functions that execute a program directly with a separate argument array, rather than building and passing a combined command string to a shell interpreter. Where shelling out genuinely can't be avoided, strict allowlist validation of the input (permitting only a specific, known-safe set of characters or values) provides meaningfully more protection than attempting to escape or blocklist dangerous characters.

For XXE, the fix is explicit and simple once known: disable external entity processing (and external DTD processing) in whatever XML parsing library your application uses, regardless of whether the current default already does this — explicit configuration removes any dependency on assumptions about library defaults that could change or be misremembered. Where possible, consider whether your application genuinely needs to accept raw XML from untrusted sources at all, since formats like JSON that don't carry this legacy entity-processing baggage eliminate the entire vulnerability class by design rather than requiring ongoing configuration vigilance.

FAQ

It's an outcome — remote code execution describes the result an attacker achieves, which can be reached through several different underlying vulnerabilities including command injection, XXE, insecure deserialization, and others.
Correctly escaping every dangerous character for every shell and operating system combination is genuinely difficult to get right consistently, and a single missed edge case can reopen the vulnerability — avoiding shell invocation entirely is more reliable than trying to escape input into it safely.
Most current major XML parsing library versions have changed their default configuration to disable external entity processing, but applications running older library versions, or ones that explicitly re-enabled the feature, remain exposed.
It depends on the specific server environment and parser configuration — in some setups, XXE combined with specific conditions can escalate toward code execution, though file disclosure and SSRF are the more universally applicable risks.
Using a language's standard library function that executes a program directly with a separate argument array, rather than constructing a single string passed to a shell interpreter, since this avoids shell metacharacter interpretation entirely.
Yes — JSON doesn't have an equivalent entity-substitution mechanism, so applications that don't need to accept XML from untrusted sources can eliminate this entire vulnerability class by not using XML for that purpose in the first place.
No — it remains a common finding in current applications specifically because many languages still make shell invocation convenient to write incorrectly, regardless of how recently the application was built.
Automated scanners typically test how an application responds to specific input patterns designed to reveal unexpected behavior, though thorough detection of these vulnerability classes usually also requires manual code review or dedicated penetration testing.
Strict allowlist validation helps significantly, but avoiding shell string construction entirely is the more fundamentally reliable fix — validation is a valuable additional layer, not a complete substitute for it.
They were originally designed for legitimate document-reuse purposes, like referencing shared boilerplate content across multiple documents — the vulnerability comes from that legitimate feature being usable to reference untrusted local files or URLs when parsing untrusted input.
📅 Last updated: August 2026📜 Sourced from: OWASP Command Injection and XXE Prevention Cheat Sheets

ToolsNovaHub guides are researched against primary sources (RFCs, vendor docs) and kept up to date as standards change. Spotted an error? Let us know.

📋 Related Tools & Guides Comparison

ResourceTypeLink
Website Security ScannerToolOpen Tool →
File Inclusion & Path Traversal VulnerabilitiesGuideRead Guide →
SSRF: Server-Side Request Forgery ExplainedGuideRead Guide →
Common Website Vulnerabilities ChecklistGuideRead Guide →
Try it yourself — 100% free
🚀 Open Website Security Scanner

🔗 More Guides