shell_sanitize_rules/lib.rs
1//! Built-in sanitization rules and ready-made presets for [`shell_sanitize`].
2//!
3//! # Quick start
4//!
5//! Use a [preset](presets) matched to your use case:
6//!
7//! ```
8//! use shell_sanitize_rules::presets;
9//!
10//! // AI agent validates a file path argument
11//! let s = presets::file_path();
12//! assert!(s.sanitize("uploads/photo.jpg").is_ok());
13//! assert!(s.sanitize("../../etc/passwd").is_err());
14//!
15//! // Value interpolated into `sh -c "..."`
16//! let s = presets::shell_command();
17//! assert!(s.sanitize("my-branch").is_ok());
18//! assert!(s.sanitize("branch; rm -rf /").is_err());
19//! ```
20//!
21//! See [`presets`] module for the full preset catalogue and AI agent
22//! architecture guidance.
23//!
24//! # Rule overlap policy
25//!
26//! Some characters are covered by multiple rules with different intent:
27//!
28//! | Character | Rules | Rationale |
29//! |-----------|-------|-----------|
30//! | `$` | `ShellMetaRule`, `EnvExpansionRule` | Meta rejects the char; Env identifies the variable name |
31//! | `{`, `}` | `ShellMetaRule`, `GlobRule` | Meta catches brace expansion; Glob catches filename patterns |
32//! | `\n`, `\r` | `ShellMetaRule`, `ControlCharRule` | Meta catches command splitting; Control catches all C0 chars |
33//!
34//! When multiple rules are active, each reports its own violations independently.
35//! This is intentional — overlapping reports give richer context about *why* an
36//! input was rejected. Callers who need unique violations can deduplicate by
37//! `(position, fragment)`.
38
39mod charset;
40mod control_char;
41mod env_expansion;
42mod glob;
43mod path_traversal;
44pub mod presets;
45mod shell_meta;
46
47pub use control_char::ControlCharRule;
48pub use env_expansion::EnvExpansionRule;
49pub use glob::GlobRule;
50pub use path_traversal::PathTraversalRule;
51pub use shell_meta::ShellMetaRule;
52
53/// Convenience: build a [`shell_sanitize::Sanitizer`] with all default rules.
54pub fn default_shell_rules() -> Vec<Box<dyn shell_sanitize::Rule>> {
55 vec![
56 Box::new(ControlCharRule::default()),
57 Box::new(ShellMetaRule::default()),
58 Box::new(PathTraversalRule::default()),
59 Box::new(GlobRule::default()),
60 Box::new(EnvExpansionRule::default()),
61 ]
62}