Passing a non-literal argument to Command::new("sh").arg("-c").arg(...) (or another shell variant) lets the shell interpret the argument as a script. If any part of that argument comes from user-controlled input, an attacker can append shell metacharacters (;, &&, `, $(...)) to inject arbitrary commands. Pass arguments directly to the target binary without a shell wrapper, or rigorously validate and escape the input.
usestd::process::Command;asyncfnbad(){letuser_input=std::env::args().nth(1).unwrap();// .arg().arg() chain
let_=Command::new("sh").arg("-c").arg(user_input.clone()).output();// Full path
let_=Command::new("/bin/sh").arg("-c").arg(user_input.clone()).output();// format! macro — non-literal
let_=Command::new("sh").arg("-c").arg(format!("ls {}",user_input)).output();// Other shell
let_=Command::new("zsh").arg("-c").arg(&user_input).output();// Fully qualified path — tokio
let_=tokio::process::Command::new("sh").arg("-c").arg(&user_input).output();// Fully qualified path — std::process
let_=std::process::Command::new("bash").arg("-c").arg(&user_input).output();// .args array form
let_=Command::new("sh").args(["-c",&user_input]).output();}
Compliant Code Examples
usestd::process::Command;fnok(){// Hardcoded shell script — not tainted
let_=Command::new("sh").arg("-c").arg("ls -la").output();// Not a shell binary
letuser_input=std::env::args().nth(1).unwrap();let_=Command::new("ls").arg(&user_input).output();// Shell binary but not -c
let_=Command::new("sh").arg("--version").output();// Structural match but @flag predicate filters out "-v"
let_=Command::new("sh").arg("-v").arg(&user_input).output();// No shell wrapper — args passed directly to the target binary
let_=Command::new("grep").arg("pattern").arg(&user_input).output();// Raw string — exercises the raw_string_literal branch of the JS guard
let_=Command::new("sh").arg("-c").arg(r"echo hi").output();// .args form with both literals
let_=Command::new("sh").args(["-c","ls -la"]).output();// .args form but not a shell binary
let_=Command::new("ls").args(["-l",&user_input]).output();}
Seamless integrations. Try Datadog Code Security
Datadog Code Security
Try this rule and analyze your code with Datadog Code Security
How to use this rule
1
2
rulesets:- rust-security # Rules to enforce Rust security.
Create a static-analysis.datadog.yml with the content above at the root of your repository
Use our free IDE Plugins or add Code Security scans to your CI pipelines