You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pure Rust ModSecurity implementation with full OWASP CRS compatibility.
A complete ModSecurity rule engine written in Rust with zero C/C++ dependencies. Load and execute OWASP Core Rule Set (CRS) rules for web application firewall (WAF) functionality in any Rust application.
Performance: 10-30x Faster than libmodsecurity
Benchmark
zentinel-modsec
libmodsecurity (C++)
Speedup
Clean request
161 ns
4,831 ns
30x faster
SQLi detection
295 ns
5,545 ns
19x faster
Body processing
1.24 µs
12.93 µs
10x faster
Rule parsing
2.75 µs
10.07 µs
3.6x faster
Throughput
6.2M req/s
207K req/s
30x higher
Features
Full OWASP CRS Compatibility - Parse and execute 800+ CRS rules
Pure Rust - No libmodsecurity, no C/C++ dependencies, no FFI
SecLang Support - Load standard ModSecurity .conf rule files
All Operators - @rx, @pm, @pmFromFile, @contains, @streq, @ipMatch, and 30+ more
All Transformations - t:lowercase, t:urlDecode, t:base64Decode, t:htmlEntityDecode, and 30+ more
Thread-Safe - Send + Sync, safe for concurrent request processing
Async-Ready - Works with tokio, async-std, or any async runtime
Zero Unsafe - #![deny(unsafe_code)]
Quick Start
Add to your Cargo.toml:
[dependencies]
zentinel-modsec = "0.1"
Basic Usage
use zentinel_modsec::ModSecurity;fnmain() -> zentinel_modsec::Result<()>{// Compile rules once; reuse the engine for all requests.let modsec = ModSecurity::from_string(r#" SecRuleEngine On SecRule REQUEST_URI "@contains /admin" \ "id:1,phase:1,deny,status:403,msg:'Admin access blocked'" "#)?;// Process a requestletmut tx = modsec.new_transaction();
tx.process_uri("/admin/dashboard","GET","HTTP/1.1")?;
tx.add_request_header("Host","example.com")?;
tx.add_request_header("User-Agent","Mozilla/5.0")?;
tx.process_request_headers()?;// Check for intervention (block/redirect/etc)ifletSome(intervention) = tx.intervention(){println!("Blocked: status={}, rules={:?}",
intervention.status,
intervention.rule_ids);}Ok(())}
Loading OWASP CRS Rules
use zentinel_modsec::ModSecurity;fnmain() -> zentinel_modsec::Result<()>{// Point at an entry file that `Include`s crs-setup.conf and the rule files// (CRS ships such a layout), or a single combined ruleset file.let modsec = ModSecurity::from_file("/etc/modsecurity/main.conf")?;println!("Loaded {} rules", modsec.rule_count());Ok(())}
SQL Injection Detection
use zentinel_modsec::ModSecurity;fnmain() -> zentinel_modsec::Result<()>{let modsec = ModSecurity::from_string(r#" SecRuleEngine On SecRule ARGS "@detectSQLi" \ "id:942100,phase:2,deny,status:403,msg:'SQL Injection detected'" "#)?;letmut tx = modsec.new_transaction();// Simulate a request with SQLi payload
tx.process_uri("/search?q=' OR 1=1--","GET","HTTP/1.1")?;
tx.process_request_headers()?;assert!(tx.has_intervention());println!("SQLi attack blocked!");Ok(())}