# Shell string command injection

User-influenced value pasted into a shell command string instead of an argument array

_Area: Web injection and code execution. Seen in 17 disclosed reports; 8 confirmed bounties, median $3,500, range $512-$33,510; latest 2026-10-23. Updated 2026-10-23._

## How it works
Code builds a shell command by pasting a user-controlled value into a string, then hands that string to a shell (`popen`, `system`, `execSync`, backticks, `@exec`). The shell re-parses the string, so any metacharacter in the value (`;`, `|`, `$()`, backticks, quotes, spaces, newline) starts or alters a command. The broken assumption is that the value is "just data" — once it reaches a shell string it is code. The same failure appears when a value is escaped at most interpolation points but one is missed, or when a value is trusted because it came from an internal API response rather than the request.

## Where it shows up
- String interpolation into a command passed to `popen`/`system`/`execSync`/backticks, e.g. `gzip -dc #{path} | wc -c` [E1](https://bugbountylibrary.com/r/h1%3A1609965.md).
- Package-manager or CLI invocations with a user-supplied target, e.g. `npm install -g pkg@${target}` [E2](https://bugbountylibrary.com/r/blog%3Asecuritylabs-datadoghq-com-articles-opencode-upgrade-remote-code-execution.md).
- Git commands built by interpolating a repo URL or path instead of argument arrays [E6](https://bugbountylibrary.com/r/blog%3Aspaceraccoon-dev-discovering-negative-days-llm-workflows.md).
- Image-processing commands built from a URL parameter [E3](https://bugbountylibrary.com/r/blog%3Asamcurry-net-how-i-couldve-taken-over-the-production-server-of-a-yahoo-acquisition-through-command-injection.md).
- Values written to a field later interpolated into a shell string, where validation is bypassed via an alternate write path (backup restore, DB import) [E4](https://bugbountylibrary.com/r/h1%3A214022.md).
- Chat/command arguments forwarded to a backing script via `@exec` without escaping [E5](https://bugbountylibrary.com/r/h1%3A851807.md).
- User-writable metadata (dataset `extra` fields) templated into a bash command [E7](https://bugbountylibrary.com/r/h1%3A2705661.md).
- Upload filename parameter passed to a shell even when file content is validated [E8](https://bugbountylibrary.com/r/blog%3Ablog-voorivex-team-uncovering-a-command-injection-2400-bounty.md).

## How to review
Trace every value reaching a shell sink back to its source. The invariant: no user-influenced value may be concatenated into a shell string. Commands must be built as argument arrays with no shell (`execFile`/`spawn` with an array, Ruby `system("cmd", arg)` or `Shellwords.escape`), or the value must be strictly validated against an allowlist. Argument arrays still need flag-injection guards: reject values starting with `-` so they cannot become options.

Then check paths that bypass normal validation:
- For import/migration pipelines, follow the raw attribute hash into the CreateService and confirm each setter filters the field before it reaches the sink [E1](https://bugbountylibrary.com/r/h1%3A1609965.md).
- For alternate write paths, check whether backup restore or DB import can set a field that normal validation would reject [E4](https://bugbountylibrary.com/r/h1%3A214022.md).
- For `@exec`-style forwarding, confirm arguments are escaped, not just passed through [E5](https://bugbountylibrary.com/r/h1%3A851807.md).
- For sanitizers, diff the blacklist against the full metacharacter set including newline, tab, `$IFS`, backticks.

## Variants seen
- Attacker-controlled `import_source` reaching `gzip -dc` shell string via bulk import pipeline [E1](https://bugbountylibrary.com/r/h1%3A1609965.md).
- User target into `npm install -g`; injection is the sink, content-type confusion is only the cross-origin reachability path [E2](https://bugbountylibrary.com/r/blog%3Asecuritylabs-datadoghq-com-articles-opencode-upgrade-remote-code-execution.md).
- URL parameter into ImageMagick command on a PHP endpoint [E3](https://bugbountylibrary.com/r/blog%3Asamcurry-net-how-i-couldve-taken-over-the-production-server-of-a-yahoo-acquisition-through-command-injection.md).
- Username into backtick `gzip` in an export job; validation bypassed via backup restore [E4](https://bugbountylibrary.com/r/h1%3A214022.md).
- Chat command arguments into `@exec`; `$(...)` evaluated by the shell [E5](https://bugbountylibrary.com/r/h1%3A851807.md).
- Interpolated repo URL in `execSync git clone`, reached via a trojanized dependency [E6](https://bugbountylibrary.com/r/blog%3Aspaceraccoon-dev-discovering-negative-days-llm-workflows.md).
- Dataset `extra` metadata into a bash command in a shipped example DAG [E7](https://bugbountylibrary.com/r/h1%3A2705661.md).
- Upload filename into a shell call, bypassing extension filters [E8](https://bugbountylibrary.com/r/blog%3Ablog-voorivex-team-uncovering-a-command-injection-2400-bounty.md).

## Why fixes fail
Escaping applied to some fields but not others leaves the missed field exploitable [E4](https://bugbountylibrary.com/r/h1%3A214022.md). Validation on the normal write path does not protect a field an alternate path (backup restore, import) can set [E4](https://bugbountylibrary.com/r/h1%3A214022.md).

## Impact and severity
Reached production-server RCE [E3](https://bugbountylibrary.com/r/blog%3Asamcurry-net-how-i-couldve-taken-over-the-production-server-of-a-yahoo-acquisition-through-command-injection.md), RCE via bulk import [E1](https://bugbountylibrary.com/r/h1%3A1609965.md), and RCE from a low-privileged user through shipped example code [E7](https://bugbountylibrary.com/r/h1%3A2705661.md). Severity rises with pre-auth reachability, root context, and cross-origin reachability [E2](https://bugbountylibrary.com/r/blog%3Asecuritylabs-datadoghq-com-articles-opencode-upgrade-remote-code-execution.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1609965.md
- E2: https://bugbountylibrary.com/r/blog%3Asecuritylabs-datadoghq-com-articles-opencode-upgrade-remote-code-execution.md
- E3: https://bugbountylibrary.com/r/blog%3Asamcurry-net-how-i-couldve-taken-over-the-production-server-of-a-yahoo-acquisition-through-command-injection.md
- E4: https://bugbountylibrary.com/r/h1%3A214022.md
- E5: https://bugbountylibrary.com/r/h1%3A851807.md
- E6: https://bugbountylibrary.com/r/blog%3Aspaceraccoon-dev-discovering-negative-days-llm-workflows.md
- E7: https://bugbountylibrary.com/r/h1%3A2705661.md
- E8: https://bugbountylibrary.com/r/blog%3Ablog-voorivex-team-uncovering-a-command-injection-2400-bounty.md
