zentinel-modsec
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: 4-11x Faster than libmodsecurity
| Benchmark | zentinel-modsec | libmodsecurity (C++) | Speedup |
|---|---|---|---|
| Clean request | 1.34 µs | 5.65 µs | 4.2x faster |
| SQLi detection | 1.40 µs | 16.03 µs | 11.5x faster |
| Body processing | 1.45 µs | 12.91 µs | 8.9x faster |
| Rule parsing (complex) | 2.73 µs | 10.58 µs | 3.9x faster |
| Throughput (clean) | 676K req/s | 168K req/s | 4.0x higher |
| Throughput (attack) | 701K req/s | 62K req/s | 11.3x higher |
Both engines run the same ruleset through request phases 1 and 2 on the same
machine (Apple M-series, single thread, criterion). Ratios matter more than the
absolute numbers, which are hardware-dependent. Reproduce with
cargo bench --features libmodsec-compare.
Earlier numbers were wrong. This table previously claimed 10-30x and 6.2M req/s. Those figures came from a benchmark that never executed the detection rules on the zentinel-modsec side — the ruleset's detection rule is
phase:2, but the measured section stopped after phase 1, and the attack payloads did not match the rule's pattern in the first place. That was true of both engines, so the comparison measured transaction setup overhead on an empty ruleset rather than rule evaluation. Body-processing and rule-parsing figures always ran the rule and were unaffected. Reported in #15 and corrected in the benchmark; these numbers are the re-measurement.Re-measured again after #17 and #18 (SecRuleUpdateTargetById, MULTIPART_PART_HEADERS population and the chain-semantics fix), which add real per-request work: throughput moved from 797K to 676K req/s and the headline from 4-13x to 4-11x.
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
.confrule files - Built-in Detection - Native
@detectSQLiand@detectXSSoperators (pure Rust libinjection) - 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:
[]
= "0.1"
Basic Usage
use ModSecurity;
Loading OWASP CRS Rules
use ModSecurity;
SQL Injection Detection
use ModSecurity;
XSS Detection
use ModSecurity;
Request Body Inspection
use ModSecurity;
Detection-Only Mode
use ModSecurity;
Anomaly Scoring
use ModSecurity;
Framework Integration
Axum
use ;
use ModSecurity;
use Arc;
async
async
Actix-web
use ;
use ModSecurity;
use Arc;
async
Supported SecLang Directives
Directives
| Directive | Status | Description |
|---|---|---|
SecRule |
✅ | Main rule directive |
SecAction |
✅ | Unconditional action |
SecMarker |
✅ | Named marker for skipAfter |
SecRuleEngine |
✅ | On/Off/DetectionOnly |
SecRequestBodyAccess |
✅ | Enable body inspection |
SecResponseBodyAccess |
✅ | Enable response inspection |
Include |
✅ | Include other rule files |
Operators
| Operator | Status | Description |
|---|---|---|
@rx |
✅ | Regular expression |
@pm |
✅ | Phrase match (Aho-Corasick) |
@pmFromFile |
✅ | Phrase match from file |
@contains |
✅ | String contains |
@streq |
✅ | String equals |
@beginsWith |
✅ | String begins with |
@endsWith |
✅ | String ends with |
@within |
✅ | Value within list |
@eq, @ne, @gt, @ge, @lt, @le |
✅ | Numeric comparison |
@detectSQLi |
✅ | SQL injection detection |
@detectXSS |
✅ | XSS detection |
@ipMatch |
✅ | IP/CIDR matching |
@validateUrlEncoding |
✅ | URL encoding validation |
@validateUtf8Encoding |
✅ | UTF-8 validation |
Transformations
| Transformation | Status | Description |
|---|---|---|
t:lowercase |
✅ | Convert to lowercase |
t:uppercase |
✅ | Convert to uppercase |
t:urlDecode |
✅ | URL decode |
t:urlDecodeUni |
✅ | URL decode (Unicode) |
t:base64Decode |
✅ | Base64 decode |
t:base64Encode |
✅ | Base64 encode |
t:htmlEntityDecode |
✅ | HTML entity decode |
t:removeWhitespace |
✅ | Remove whitespace |
t:compressWhitespace |
✅ | Compress whitespace |
t:normalizePath |
✅ | Normalize path |
t:normalizePathWin |
✅ | Normalize Windows path |
t:cmdLine |
✅ | Command line normalization |
t:md5 |
✅ | MD5 hash |
t:sha1 |
✅ | SHA1 hash |
t:hexEncode |
✅ | Hex encode |
t:hexDecode |
✅ | Hex decode |
Actions
| Action | Status | Description |
|---|---|---|
deny |
✅ | Block request |
block |
✅ | Block with default status |
pass |
✅ | Continue processing |
allow |
✅ | Skip remaining rules |
redirect |
✅ | Redirect to URL |
drop |
✅ | Drop connection |
chain |
✅ | Chain to next rule |
skip |
✅ | Skip N rules |
skipAfter |
✅ | Skip to marker |
setvar |
✅ | Set variable |
capture |
✅ | Capture regex groups |
id |
✅ | Rule ID |
phase |
✅ | Processing phase |
severity |
✅ | Severity level |
msg |
✅ | Log message |
tag |
✅ | Rule tag |
Why Pure Rust?
- Performance - 4-11x faster than C++ libmodsecurity, depending on workload
- Safety - Memory safety guaranteed, no buffer overflows
- Portability - Runs anywhere Rust compiles (including WASM)
- Simplicity -
cargo add zentinel-modsec, no system dependencies - Auditability - Single-language codebase, easier security review
Technical Optimizations
- PHF (Perfect Hash Functions) - O(1) operator/variable lookup
- Lazy Regex Compilation - Defer compilation to first use
- Aho-Corasick - O(n) multi-pattern matching for
@pm - RegexSet - Single-pass multi-regex evaluation for XSS detection
- Zero-Copy Parsing -
Cow<str>avoids allocations when possible - No FFI Overhead - Pure Rust, no cross-language calls
OWASP CRS Setup
# Download OWASP Core Rule Set
# Create an entry file that pulls in the setup and rule files
// Then load the entry file from your application:
let modsec = from_file?;
Comparison
| Feature | zentinel-modsec | libmodsecurity | mod_security |
|---|---|---|---|
| Language | Pure Rust | C++ | C |
| Dependencies | None | PCRE, libxml2, etc. | Apache/nginx |
| Performance | 676K req/s | 168K req/s | ~200K req/s |
| CRS Compatible | ✅ | ✅ | ✅ |
| WASM Support | ✅ | ❌ | ❌ |
| Memory Safety | ✅ Guaranteed | ❌ Manual | ❌ Manual |
License
Apache-2.0
Contributing
Contributions welcome! Please read CONTRIBUTING.md for guidelines.
Related Projects
- Zentinel - Extensible reverse proxy using this engine
- OWASP CRS - Core Rule Set for ModSecurity
- libmodsecurity - Original C++ implementation