- XML and JSON are handled very differently in ModSecurity.
- This has direct impact on memory usage and security.
- A JSON library alone is not sufficient for security.
- A dedicated control layer is required to enforce limits and guarantee safe behavior.
- Uses libxml2
- Combines:
- DOM (
xmlDoc) → full tree in memory - SAX → for ARGS extraction
- DOM (
Issues:
- ❌ No clearly enforced depth/node limits visible in analyzed code
- ❌ Potentially high memory usage due to DOM
Risk:
Full tree construction may lead to memory exhaustion or DoS scenarios.
- Uses YAJL (event-based / streaming parser)
- No DOM construction in ModSecurity code
- BUT:
- Entire request body is buffered first
Resulting model:
Full request body in memory → streaming parsing on top
- ✅
SecRequestBodyJsonDepthLimit→ limits nesting depth - ✅
SecRequestBodyLimit→ limits total body size - ✅
SecArgumentsLimit→ limits extracted parameters
- ❌ Maximum array size
- ❌ Maximum number of keys
- ❌ Maximum string length
- ❌ JSON-specific memory limits
- ❌ No explicit depth limit visible
- ❌ DOM tree is constructed
⚠️ Limits may apply too late
The most critical factor is when limits are enforced.
GOOD: during parsing → early abort BAD: after parsing → too late
- Switching to DOM/tree-based parser:
- ❌ higher memory usage
- ❌ limits applied too late
- ❌ weaker DoS protection
A new JSON library must:
- support streaming/event-based parsing
- allow early abort during parsing
- avoid building full JSON trees by default
-
RapidJSON
- SAX + optional DOM
- streaming support
- header-only
-
jsoncons
- feature-rich
- streaming + schema support
- more complex
-
nlohmann/json
- easy to use
⚠️ default usage is DOM-based
-
simdjson
- very fast
- different (lazy/on-demand) model
- not a direct SAX replacement
- json-c
- Jansson
- cJSON
- JsonCpp
- yyjson
- Glaze
→ primarily DOM/object-based
Blaze is not a parser.
- JSON Schema validation
- enforcing structure rules (types, required fields, etc.)
- streaming parsing
- early-abort enforcement
- replacing YAJL
Correct usage:
Parser → Control Layer → (optional) Schema Validator (Blaze)
[ HTTP Body ] ↓ [ Streaming JSON Parser ] ↓ [ Control Layer (custom logic) ] ↓ [ ModSecurity (ARGS, rules) ] ↓ [ optional: Schema Validator ]
- Maximum depth
- Number of keys / elements
- Array sizes
- String lengths
- Memory constraints
Parser → Callback → Control Logic → STOP immediately
Without early abort, protection is significantly weakened.
- Controlled JSON → ARGS mapping
- Prevent parameter explosion
- Maintain consistent WAF behavior
- Replacing parser without architecture changes
- Using DOM-based parsing without strict limits
- Applying limits only after full parsing
- Assuming the library handles security
- XML is currently more risky due to DOM usage and missing limits.
- JSON is better protected, but still incomplete.
- Security does not come from the library.
- Security comes from a control layer enforcing limits during parsing.
A JSON library is just a parser.
Security only exists if a control layer enforces limits and guarantees early abort behavior.