Security

    Command injection in mobile apps

    A 2026 view of command injection where untrusted input adds extra commands to a shell command, contrasted with passing arguments as a list to a non-shell API

    Command injection is the bug where code builds an operating-system command out of untrusted input and runs it, letting an attacker tack on commands of their own. It is most associated with servers, but it touches mobile in two ways: an Android app or native code that shells out to run a command, and, more often, the app's backend running OS commands built from values the app sends. The impact when it works is severe, running arbitrary commands in the context of the app or server. The good news is that the fix is mostly about not building command strings from input, and frequently about not shelling out at all. Here is what command injection is, where it appears, and how to prevent it.

    Short answer

    Command injection (OS command injection) is a vulnerability where an application builds an operating-system command from untrusted input and executes it, letting an attacker inject additional commands that run in the app's or server's context. Per CWE-78, the impact can be arbitrary command execution, which is severe. In mobile, it appears where an Android app or native code invokes a shell command with user input, and more commonly where the app's backend runs OS commands built from values the app sends. The defenses are to avoid invoking OS commands where a library can do the job, and when a command is unavoidable, never build a command string from untrusted input: pass arguments as a separate list to an API that does not invoke a shell, and validate input strictly.

    What you should know

    • Command injection runs attacker commands: built into an OS command.
    • The impact is arbitrary command execution: in the app's or server's context.
    • Mobile apps rarely shell out: but some do, via exec-style APIs or native code.
    • The backend is the more common vector: running commands from app-supplied input.
    • The fix is to avoid shells and string-built commands: pass arguments as a list.

    What is command injection?

    It is injecting extra operating-system commands through untrusted input used to build a command. When code constructs a command line by combining a base command with input, and runs it through a shell, the shell interprets special characters in that input, command separators, pipes, substitution, so an attacker who controls part of the input can append or alter commands, and the shell executes them. So a feature meant to run one specific command with a user-supplied parameter becomes a way to run whatever the attacker writes into that parameter, with the privileges of the process that runs it. The danger is the combination of two things: building the command as a string that includes untrusted input, and running it through a shell that interprets metacharacters. Remove either, do not include untrusted input in the command, or do not invoke a shell that interprets it, and the injection does not work. It is the same untrusted-input-changing-meaning pattern as other injection flaws, applied to OS commands.

    Where does it show up in mobile?

    In a few places, more often on the backend than the client. The table lists them.

    LocationHow it arises
    Android exec-style callRunning a shell command with user input
    Native codeA C/C++ library invoking a system command
    App backendServer running OS commands built from app input
    Wrapped toolingShelling out to a tool with input as arguments
    Chained metacharactersInput adding separators, pipes, or substitution

    Mobile client apps shell out far less than servers, partly because of platform sandboxing, but it does happen: an Android app can run a command through an exec-style API, and native C or C++ code can call a system function, and if either incorporates user input into the command, it is exposed. The more common and dangerous location is the backend: a server doing image processing, file conversion, or other tasks by invoking command-line tools, building the command from values the app sends, is a classic command-injection setting, and an attacker calling the API directly supplies the malicious input. In all cases the mechanism is the same, untrusted input reaching a command run through a shell, often by adding metacharacters that chain in extra commands.

    How do you prevent it?

    Avoid shelling out, and when you must, never build the command from input. The first question is whether you need to invoke an OS command at all, since a built-in library or platform API for the task, image handling, file work, avoids the entire class. When you genuinely must run a command, do not assemble it as a string that includes untrusted input and hand it to a shell; instead use an API that takes the program and its arguments as a separate list and runs it without shell interpretation, so input becomes a single inert argument rather than something the shell can parse for metacharacters. Validate and, where possible, allowlist the input, constraining it to the narrow set of values the feature actually needs rather than accepting arbitrary strings. Avoid passing untrusted input as options or flags, and run the process with the least privilege necessary so a failure is contained. Apply this on whichever side runs the command, and remember the backend version is reachable by an attacker calling your API directly. The principle is to prefer libraries over commands, and when a command is necessary, keep untrusted input out of the command line and away from any shell.

    What to watch out for

    The first trap is building a command string with untrusted input and running it through a shell, the core bug; pass arguments as a list to a non-shell API instead. The second is assuming mobile is immune because apps rarely shell out, while the backend that serves the app runs commands from app input. The third is validating for some metacharacters but missing others, when allowlisting the input is more reliable than blocklisting characters. Command injection is a code-level flaw on whichever side runs the command, so a pre-submission scan such as PTKD.com (https://ptkd.com), which reads the binary against OWASP MASVS, assesses the app's input handling, while the backend command handling is yours to secure server-side.

    What to take away

    • Command injection runs attacker-supplied OS commands by building a command from untrusted input and executing it through a shell, with arbitrary command execution as the impact.
    • In mobile it appears in Android exec-style calls and native code, and more commonly in the app's backend running commands built from app-supplied input.
    • Prevent it by avoiding OS commands where a library suffices, and when a command is needed, passing arguments as a list to a non-shell API, validating and allowlisting input, and using least privilege.
    • Use a pre-submission scan such as PTKD.com to assess your app's input handling, and secure backend command execution server-side.
    • #command-injection
    • #cwe-78
    • #injection
    • #android
    • #backend
    • #owasp-masvs
    • #app-security

    Frequently asked questions

    What is command injection?
    It is injecting extra operating-system commands through untrusted input used to build a command. When code constructs a command line by combining a base command with input and runs it through a shell, the shell interprets special characters like separators, pipes, and substitution, so an attacker who controls part of the input can append or alter commands the shell then executes. A feature meant to run one command with a parameter becomes a way to run whatever the attacker writes, with the privileges of the running process. It is the injection pattern applied to OS commands.
    Do mobile apps actually have command-injection bugs?
    Client apps shell out far less than servers, partly due to platform sandboxing, but it does happen: an Android app can run a command through an exec-style API, and native C or C++ code can call a system function, and incorporating user input into either exposes it. The more common and dangerous location is the backend that serves the app, a server invoking command-line tools for image processing or file conversion, building the command from values the app sends, where an attacker calling the API directly supplies the malicious input. So mobile is affected on both sides.
    How do I prevent command injection?
    First, avoid invoking an OS command at all where a built-in library or platform API can do the task, which removes the entire class. When you must run a command, do not assemble it as a string including untrusted input and hand it to a shell; use an API that takes the program and its arguments as a separate list and runs without shell interpretation, so input is an inert argument rather than something a shell parses for metacharacters. Validate and allowlist the input, avoid passing it as flags, and run with least privilege so a failure is contained.
    Why is passing arguments as a list safer?
    Because it avoids the shell. Command injection needs two things: untrusted input built into the command, and a shell that interprets metacharacters in it. When you pass the program and its arguments as a separate list to an API that executes without invoking a shell, each argument is treated as a single literal value, so characters like semicolons or pipes in the input are not interpreted as command syntax, they are just part of that argument. That removes the shell-interpretation half of the problem, which is why it is preferred over building and running a command string.
    Can a scan find command injection?
    Command injection is a code-level flaw on whichever side runs the command, so the backend version is fixed in server code and the client version in the app. A pre-submission scan such as PTKD.com reads the binary against OWASP MASVS and assesses the app's input handling, which is part of identifying where untrusted input is processed, including any exec-style or native command use. The specific fixes, avoiding shells, passing arguments as a list, and allowlisting input, are applied in your code, and the backend command handling is secured server-side where the attacker can reach it directly.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free