command-injection
Skill2 starsChanged 4 months agoMITView on GitHub
SAST detection methodology for OS command injection (CWE-78), including shell metacharacter injection, argument/flag injection into git/curl/tar, wildcard injection, shell=True, and indirect injection via env vars and filenames. Use when reviewing code that spawns OS processes. Writes confirmed findings to findings/03-command-injection.md.
- Deletes or force-pushes
5 other projects use a version of this.
Adopted by
Most recently taken up by
- blacklanternsecurity/red-runtheir own version, first seen Oct 25, 2026
- cdxiaodong/cain-agenttheir own version, first seen Oct 8, 2026
- awarexone/AXguardtheir own version, first seen Sep 15, 2026
- ajtazer/heckittheir own version, first seen Sep 11, 2026
- langbyyi/websec-skillstheir own version, first seen Jun 12, 2026
Used with
Projects with it also use path-traversal.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
langbyyiSkillpath-traversal
Path traversal and LFI playbook. Use when file paths, download endpoints, include operations, archive extraction, or wrapper behavior may expose filesystem control.
Also in 3 projects that use this
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- cdxiaodong/cain-agent★ 953same name
- blacklanternsecurity/red-run★ 296same name
- awarexone/AXguard★ 17same name
- langbyyi/websec-skills★ 4same name
- ajtazer/heckit★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository49 other files it gives its agents.
- authentication-flawsSkill
- broken-access-control-idorSkill
- business-logic-flawsSkill
- cicd-and-pipeline-injectionSkill
- code-injectionSkill
- cors-misconfigurationSkill
- crlf-and-header-injectionSkill
- cross-site-scriptingSkill
- csrfSkill
- dependency-and-supply-chainSkill
- dom-clobbering-and-postmessageSkill
- graphql-injection-and-abuseSkill
- hardcoded-secretsSkill
- http-request-smugglingSkill
- iac-misconfigurationSkill
- information-disclosureSkill
- insecure-deserializationSkill
- insecure-randomnessSkill
- jwt-vulnerabilitiesSkill
- ldap-injectionSkill
- llm-and-ai-application-securitySkill
- mass-assignmentSkill
- memory-safetySkill
- mobile-android-securitySkill
- mobile-ios-securitySkill
- nosql-injectionSkill
- oauth-oidc-saml-flawsSkill
- open-redirectSkill
- path-traversal-and-file-inclusionSkill
- prototype-pollutionSkill
- race-conditions-and-toctouSkill
- redosSkill
- sast-final-reportSkill
- sast-finding-validationSkill
- sast-methodologySkill
- security-logging-and-monitoring-failuresSkill
- security-misconfiguration-and-headersSkill
- server-side-template-injectionSkill
- session-managementSkill
- smart-contract-securitySkill
- sql-injectionSkill
- ssrfSkill
- unrestricted-file-uploadSkill
- unsafe-parsers-and-yamlSkill
- weak-cryptographySkill
- web-cache-poisoning-and-deceptionSkill
- websocket-securitySkill
- xpath-and-xml-injectionSkill
- xxeSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 0 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 40
All HTTP inputs, plus indirect sources that are easy to miss: environment variables (multi-tenant/CI), filenames in uploads and archives (a …
- Very specific: line 94
Use the -- end-of-options separator and/or validate that user args don't start with - to stop flag injection (git clone -- <url>).
- Very specific: line 98
Prefer native libraries over shelling out (HTTP client vs curl, archive lib vs tar).
- Very specific: line 182
Avoid shelling out; use native libraries.
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Command Injection — SAST Methodology
Class: OS Command Injection · CWE-78 · OWASP: A03 Injection
Findings file: findings/03-command-injection.md
1. Overview
Command injection occurs when attacker-controlled data reaches a process-spawning
sink and influences either the command string interpreted by a shell or the
arguments passed to a program. Two distinct failure modes: (1) a shell parses
the input and metacharacters (;, |, &, $(), backticks) start new commands;
(2) even with no shell, input becomes an argument that the target program treats
as an option (argument/flag injection). The core test: does a source reach an
exec/system/spawn sink, and is a shell involved or can the input pose as a
flag?
2. Where it lives
- Any process-spawn API:
os.system,subprocesswithshell=True,child_process.exec,Runtime.exec,ProcessBuilder, PHPsystem/exec/passthru/shell_exec/backticks, Rubysystem/backticks/%x, Goexec.Commandwithsh -c. - Shell-outs to CLI tools (git, curl, tar, ffmpeg, imagemagick, ping, nmap, zip) with user-supplied args, filenames, or URLs.
- "Glue" scripts, webhooks, CI runners, and file-conversion/thumbnail pipelines.
- Template/report generators that call
wkhtmltopdf,pandoc,latex, etc.
3. Sources (tainted input)
All HTTP inputs, plus indirect sources that are easy to miss: environment
variables (multi-tenant/CI), filenames in uploads and archives (a file named
;rm -rf or --upload-file), image/document metadata read by a downstream tool,
DB-stored values re-used to build a command (second-order), and hostnames/URLs
passed to network tools. Trace stored/derived values back to their write source.
4. Sinks (dangerous operations)
# Python — dangerous
os.system("ping -c1 " + host) # shell parses metachars
subprocess.run(f"tar czf out.tgz {path}", shell=True) # shell=True = shell
subprocess.call(["git", "clone", url]) # NO shell, but url="--upload-pack=..." = arg injection
os.popen("convert " + name + " out.png")// Node — dangerous
child_process.exec(`ping -c1 ${host}`); // exec spawns /bin/sh
child_process.execSync("tar czf o.tgz " + path);
spawn("sh", ["-c", `ls ${dir}`]); // explicit shell
spawn("git", ["clone", url]); // arg injection if url starts with -// Java — dangerous
Runtime.getRuntime().exec("sh -c \"ping " + host + "\"");
new ProcessBuilder("bash", "-c", "grep " + q + " f").start();
Runtime.getRuntime().exec(new String[]{"tar","xf",userFile}); // arg injection// PHP — dangerous
system("ping -c1 ".$_GET['host']);
exec("convert ".$file." out.png", $o);
passthru("git clone ".$url);
$out = shell_exec("ls ".$dir);
$x = `whois $domain`; // backticks# Ruby — dangerous
system("ping -c1 #{host}") # interpolation + shell
`tar czf out.tgz #{path}` # backticks
%x(git clone #{url})// Go — dangerous
exec.Command("sh", "-c", "ping "+host).Run() // sh -c = shell
exec.Command("tar", "xf", userFile).Run() // arg injection5. Sanitizers / safe patterns
Safe:
- No shell + argument vector: pass a program and an array of args
(
subprocess.run([...], shell=False),execFile/spawnwithout a shell,ProcessBuilder(list),exec.Command(name, args...)). Metacharacters are inert. - Use the
--end-of-options separator and/or validate that user args don't start with-to stop flag injection (git clone -- <url>). - Strict allowlist for the command/subcommand; validate hostnames, paths, and IDs against a tight regex/enum.
- Prefer native libraries over shelling out (HTTP client vs
curl, archive lib vstar).
Fails / not a real sanitizer:
- Escaping quotes but still running through a shell — many metachars need no
quotes (
$(),`,\n,;). - Blocklisting
;and|while&&,\n,$(),${IFS}, backticks slip through; blocklists are always incomplete. shlex.quote/escapeshellargapplied to one arg but the command still built as a shell string, or applied but the value is later re-split.- Array/exec vector used, but the value is a flag — arg injection is unblocked by shell-escaping (there is no shell to escape).
- Validating the value but passing the raw filename from an upload/archive.
6. Detection methodology
- Find sinks: grep the spawn APIs and shell indicators.
rg -n 'os\.system|subprocess\.(run|call|Popen|check_output)|os\.popen' rg -n 'shell\s*=\s*True|child_process|\.exec(Sync)?\(|execFile|spawn\(' rg -n 'Runtime\.getRuntime\(\)\.exec|ProcessBuilder|Process\.Start' rg -n 'shell_exec|passthru|\bsystem\s*\(|\bexec\s*\(|popen|proc_open' rg -n '`[^`]*\$\{|%x\(|\bsystem\s*\(|IO\.popen|Open3' rg -n 'exec\.Command\([^)]*"(sh|bash|cmd|powershell)"' - Determine if a shell is involved:
shell=True, a string command,sh -c/cmd /c/bash -c, or an API that spawns a shell (exec,system, backticks). If yes → metacharacter injection is in scope. - If no shell, check argument injection: can input become a leading
-/--flag to the target tool? (git--upload-pack/--output, curl-o/--config, tar--to-command, find-exec, ssh-o). - Trace input to a source (direct, env, filename, or second-order). Stop at a constant.
- Check for a real neutralizer: array vector and flag guard, or a strict allowlist. Verify it's on the reaching path and not bypassable (see §5).
- Confirm reachability and note the platform (POSIX shell vs Windows
cmd/PowerShell) — quoting and metachars differ.
7. Modern & niche variants
- Argument / flag injection (no metachars needed): input passed as a program
argument that the program interprets as an option.
git clone --upload-pack='sh -c ...' host:repo,curl --config /attackeror-o /path,tar --to-command=cmd,find . -exec,ssh -o ProxyCommand=,zip -T --unzip-command. Defeats shell-escaping entirely because there is no shell. Guard with--and a leading-dash check. - Wildcard injection: attacker controls filenames in a directory later globbed
(
tar czf a.tgz *,chown -R x *). A file named--checkpoint-action=exec=shor-rfis expanded by the shell into an argument — classictar/rsync/chownwildcard attacks. - Indirect via environment variables: input written to an env var consumed by
a child process (
IFS,LD_PRELOAD,GIT_SSH,PAGER,PATH,PERL5OPT). The command string looks clean; the env is the vector. - Indirect via filenames / archives: upload or zip-slip filename becomes an arg or is globbed. Metadata (EXIF, PDF fields) read by a shelled-out tool.
shell=Trueand backtick/%xinterpolation: the most common Python/Ruby/PHP root cause — a formatted string with a shell.execvsexecvesemantics: JavaRuntime.exec(String)naively splits on spaces (no shell) — quoting breaks, andexec(String[])runs a program directly; neither parses metachars unless you explicitly invokesh -c. Know which overload is used before judging.- Windows cmd vs PowerShell:
cmd /cmetachars are&,|,%VAR%,^; PowerShell adds;,`,$(),|, and expression injection..batwrappers re-parse arguments (the "BatBadBut" class) even from array-vector spawns.
8. Common false positives
- Array/exec-file vector with no shell and no possibility of flag injection
(value is not a leading arg, or
--/dash-guard present). - Command and all args are hard-coded constants.
- User input validated against a strict allowlist/enum before use.
- A native library is used and the "command" string is unrelated dead code.
9. Severity & exploitability
Base Critical — command injection is remote code execution. Confirm and it is
Critical; pre-auth or default-config reachability keeps it there. Argument
injection may be High if it yields file write/read or option abuse short of
full RCE, rising to Critical when the flag reaches code execution (e.g. git
--upload-pack). Lower only if reachable exclusively behind strong admin auth with
constrained input. See references/severity-model.md.
10. Remediation
Avoid shelling out; use native libraries. When you must spawn, use the
array/argument vector with shell=False and never build a shell string. Add a
strict allowlist for commands and validate every argument; use -- and reject
values starting with -. Never pass raw filenames/env into commands. Run with
least privilege.
11. Output
Append each confirmed finding to findings/03-command-injection.md using
references/finding-template.md. Set Class: OS Command Injection, CWE:
CWE-78, and in Chain potential name primitives such as remote code
execution (terminal primitive — usually the end of a chain), arbitrary file
read/write (via flag injection / redirection), or note when it consumes a
primitive like arbitrary file write or SSRF (a controlled URL fed to curl)
to reach RCE.
Primitives (controlled): provides CODE_EXEC; consumes none
References
- CWE-78; OWASP A03:2021 Injection; OWASP Command Injection Prevention Cheat Sheet; GTFOBins/LOLBAS (argument-injection gadgets).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

