JSON body test evidence showing a clean JSON HTTP 200 result, SQLi-like and XSS-like HTTP 403 results, and OWASP CRS rule IDs.
Across both stacks, the clean JSON body was allowed twice while the SQLi-like and XSS-like JSON fields were blocked four times.

    Lab status

    Product
    JSON body inspection with ModSecurity and Coraza
    Status
    Completed hands-on test
    Updated
    2026-07-26

    Evidence policy

    WAFWiki separates verified smoke-test results from architecture diagrams and methodology notes. A smoke test proves one narrow local path; it does not claim full production readiness.

    Environment

    Reproducibility notes

    Content type

    application/json

    Request route

    POST /anything on go-httpbin 2.21.0

    Rule set

    OWASP CRS 4.25.0 on both stacks, request-body inspection enabled by the selected defaults

    ModSecurity stack

    ModSecurity 3.0.16 + ModSecurity-nginx 1.0.4

    Coraza stack

    Coraza 3.7.0 + coraza-caddy 2.5.0 + Caddy 2.11.2

    JSON cases

    Clean order note, SQLi-like username field, and XSS-like comment field

    Commands

    How this lab can be reproduced

    Send a clean JSON body

    curl -i -X POST -H 'Content-Type: application/json' \
      --data '{"name":"Alice","note":"order 123"}' \
      http://127.0.0.1:18182/anything

    The clean JSON body returns HTTP 200 through the Coraza path in this recorded configuration.

    Run the controlled JSON cases

    scripts/run-waf-evidence-lab.sh

    The script sends the same three JSON bodies through both WAF stacks and records six decisions.

    Extract JSON rows

    awk -F, 'NR == 1 || $2 ~ /json/ { print }' \
      docs/lab-evidence/waf-engine-comparison-2026-07-26-requests.csv

    Six JSON rows are shown: two clean HTTP 200 decisions and four controlled HTTP 403 decisions.

    Observed result

    What the hands-on test showed

    Clean JSON body

    2 / 2 returned 200

    The same benign order-style JSON object reached the upstream through both stacks.

    SQLi-like JSON field

    2 / 2 returned 403

    Both stacks identified the username field with CRS rule 942100 and exceeded the blocking threshold.

    XSS-like JSON field

    2 / 2 returned 403

    Both stacks identified the comment field with CRS rule 941100; additional XSS rules also appeared in logs.

    Parsed field evidence

    ARGS:json.* visible

    Logs referenced ARGS:json.username and ARGS:json.comment rather than treating the body as an opaque string.

    clean body: {name: Alice, note: order 123} -> 200 on both stacks
    SQLi-like field: json.username -> CRS 942100 -> 403 on both stacks
    XSS-like field: json.comment -> CRS 941100 -> 403 on both stacks
    blocking evaluation: CRS 949110
    JSON decisions: 6 total, 6 matched expectations

    Evidence context

    The JSON subset used the same route and request bodies on both paths.

    The evidence confirms body-field parsing for these three objects. It does not establish behavior for every JSON shape, content-type variation, parser ambiguity, or body-size limit.

    Shared WAF JSON body test topology showing the same requests sent through ModSecurity NGINX and Coraza Caddy to one upstream.

    Open evidence

    Download the sanitized result files.

    The files expose the status matrix and versioned summary without publishing raw container logs or unrelated local data.

    Download evidence summary JSON

    Pinned image IDs, component versions, host details, request results, latency samples, resource snapshots, and limitations.

    Limitations

    What this result does not prove

    Related research

    Continue researching JSON body inspection with ModSecurity and Coraza