shell-sanitize
Type-safe input sanitization for shell arguments and file paths.
Reject, don't escape — this crate rejects dangerous input with a clear error instead of trying to transform it into something "safe".
When to use this crate
Prefer [std::process::Command] when possible. Passing arguments
via Command::new("git").arg(user_input) bypasses the shell entirely
and is always the safest option.
This crate is for situations where shell evaluation is unavoidable:
| Scenario | Why you can't avoid the shell |
|---|---|
| SSH remote commands | Remote side evaluates through shell |
docker exec ctr sh -c "..." |
Container-side shell |
CI/CD pipeline run: blocks |
YAML → shell evaluation |
| AI agent tool execution | LLM output may reach a shell |
Legacy system() / popen() |
API forces shell involvement |
It is also valuable for path validation even without shell involvement:
blocking ../../etc/passwd in upload paths, config file references, and
template includes.
Crates
| Crate | Description |
|---|---|
shell-sanitize |
Core framework: Rule trait, Sanitizer builder, Sanitized<T> proof type |
shell-sanitize-rules |
Built-in rules and ready-made presets |
Quick start
[]
= "0.1"
use presets;
// AI agent validates a file path argument
let s = file_path;
assert!;
assert!;
// Value interpolated into `sh -c "..."`
let s = shell_command;
assert!;
assert!;
Presets
| Preset | Target context | Rules |
|---|---|---|
command_arg() |
Command::new().arg() |
ControlChar |
shell_command() |
sh -c, SSH, popen |
ShellMeta + ControlChar + EnvExpansion + Glob |
file_path() |
Upload dest, include | PathTraversal + ControlChar |
file_path_absolute() |
Config file, absolute OK | PathTraversal(allow_abs) + ControlChar |
strict() |
SSH remote path ops, max protection | All 5 rules |
Custom rules
Implement the Rule trait from shell-sanitize to create your own rules:
use ;
;
let sanitizer = builder
.add_rule
.build;
Defense in depth for AI agents
AI Agent Framework
┌──────────────────────────────────────────┐
│ │
│ Path-based tools Bash tool │
│ (Read/Write/Glob) (free-form) │
│ │ │ │
│ ▼ ▼ │
│ ★ shell-sanitize ★ Sandbox/Container
│ file_path() preset (OS-level isolation)
│ file_path_absolute() │
│ │
└──────────────────────────────────────────┘
Scope: argument validation, not command validation
This crate validates individual arguments and paths — it does not parse or validate entire shell command strings. Sanitizing an entire command string would break legitimate syntax (pipes, redirects, subshells). Separate the trusted command structure from untrusted data, then validate only the data.
Known limitations
- Free-form command strings — use sandbox/container isolation
- Argument injection (
--upload-pack=evil) — use--separators or command-specific validation - URL-encoded bypasses (
%2e%2e) — decode input before sanitizing - Semantic attacks — a path like
safe/but/wrong/file.txtpasses all rules but may still be the wrong file
License
Licensed under either of
at your option.