Protocol parsers
Engines live
Detection engines should never have to know whether a value arrived as JSON, a
form field or a SOAP node. The parsers make that true: each one understands a
single wire format and flattens it into the same canonical Params, tagged
with a Source.
One surface, many formats
Whatever the content type, the output is a flat list of {Source, Name, Raw}
parameters. A deeply nested JSON body and a query string become the same shape of
detection surface — so an SQLi engine written once works against every input
location.
| Parser | Source tag | Trigger |
|---|---|---|
| Query | Query |
URL query string (always) |
| Form | Form |
application/x-www-form-urlencoded body |
| Headers & cookies | Header / Cookie |
allowlisted headers + cookies (gated by -scan-headers) |
| JSON | JSON |
JSON body — recursive flatten with dotted / [i] paths |
| Multipart | Multipart |
multipart/form-data parts |
| GraphQL | GraphQL |
GraphQL query + variables |
| XML | XML |
XML body — elements and attributes |
| SOAP | SOAP |
SOAP envelope (always attempted) |
| JWT | JWT |
bearer / JWT — decoded claims (always attempted) |
| WebSocket | WebSocket |
handshake headers; frames relayed post-101 |
Content-type gating
The engine picks the body parser from the content type (isJSONBody,
isFormBody, isMultipartBody, isGraphQLBody, isXMLBody), while a few parsers
run unconditionally because their input can hide anywhere: SOAP (envelope
detection) and JWT (any bearer token) are always attempted, and the query and
allowlisted headers are always parsed. The JWT parser also feeds the auth engine —
an alg: none token becomes a finding.
Flattening, with structure preserved
Nested structures are flattened with their path encoded in the parameter name, so structure is not lost — it becomes queryable. A JSON body
flattens to params named user.roles[0], user.roles[1]. The API engine uses
this to catch deep-nesting denial-of-service and mass-assignment of
privilege-flag fields.
WebSocket
The WebSocket path is special: the handshake headers are parsed like any request,
and if it is a genuine upgrade the connection switches to frame relay, where
post-101 frames are still inspected rather than blindly tunnelled.
Built for hostile input
Every parser is zero-allocation on the hot path and fuzzed. They are written to never panic on malformed, truncated or adversarial input, and to bound their work so a pathological body cannot exhaust CPU or memory. The parser output is written into a per-request arena that is reset and reused between requests.
Status
All seven structured parsers plus urlencoded forms are built and fuzzed; the protocol-parser milestone is complete. Each parser has its own contract spec backed by test vectors.