Repository navigation
v2: Return HTTP 400 for JSON completion errors without relaxing rejection - #3629
vortexopenclaw wants to merge 2 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
| Layer / File(s) | Summary |
|---|---|
JSON completion status mapping apache2/msc_reqbody.c, apache2/apache2_io.c |
JSON completion failures on non-empty bodies now return -2. Apache maps -2 to HTTP 400. The function documentation describes the return codes. |
JSON EOF regression coverage tests/regression/rule/15-json-eof.t |
Tests cover incomplete JSON, empty and valid bodies, in-stream syntax errors, rule handling, and disabled request-body processing. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Possibly related issues
- owasp-modsecurity/ModSecurity issue 3655: The change introduces a distinct internal result code for JSON completion failures, which relates to the issue’s report about unnamed negative failure codes.
- owasp-modsecurity/ModSecurity issue 3581: The change addresses JSON completion error handling, but the supplied summary says it retains early rejection and DetectionOnly behavior.
Suggested reviewers: fzipi, airween
Merge Risk: 
Minimal · previous review 9804b
-
The change is ready for normal merge checks: JSON completion failures receive HTTP 400, with no established regression in other request-body handling.
Pre-merge checks: 
4
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
🔵 Needs a closer look
Security-sensitive request-body handling and outstanding upstream CI/quality gates require maintainer review.
Pull request overview
Updates ModSecurity v2 to return HTTP 400 for JSON completion failures while preserving unconditional rejection and JSON inspection.
Changes:
- Adds a distinct JSON completion-failure result.
- Maps completion failures to HTTP 400.
- Adds comprehensive regression coverage.
File summaries
| File | Description |
|---|---|
tests/regression/rule/15-json-eof.t |
Adds JSON completion and rejection regression tests. |
apache2/msc_reqbody.c |
Identifies JSON completion failures separately. |
apache2/apache2_io.c |
Maps JSON completion failures to HTTP 400. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
fzipi
left a comment
There was a problem hiding this comment.
Thanks @vortexopenclaw for the very thorough write-up and test matrix!
What I checked:
- I built this head and v2/master in an Ubuntu 24.04 container (Apache 2.4.58, YAJL) and ran the new
.tfiles against both. On v2/master a truncated JSON body ({) gets a 500 before phase 2, including under DetectionOnly. With this PR it's a 400.15-json-eof.t: 14/14 pass on the PR; on the base, exactly the 7 completion-status cases fail.10-request-buckets.t: 24/24 pass on both.
- The full regression suite, on the PR head and on the PR merged into current v2/master, shows the same 13 environmental failures as the base and no new ones (the XML body tests included).
- The
-2return frommodsecurity_request_body_end()can't collide with anything: the urlencoded/raw paths only return-1, andread_request_body()is the only caller.
So the actual fix looks right to me. Some things to sort out before we can merge:
- (blocking) Please split the
read_request_body()refactor (check_request_body_limit/store_request_body_chunk/read_request_body_bucket) and10-request-buckets.tinto a separate PR. I walked through the branches and they look equivalent, and the bucket tests pass on the unrefactored base too. But it's ~200 lines of churn in the request-body reader on the maintenance branch for what is a ~10-line status-code fix, and we keep functional changes and refactors apart. This PR should be the-2return, the 400 mapping, and the JSON tests. - (blocking) This overlaps #3515, which makes the same JSON change plus XML/multipart. We need to pick one direction and not merge both. Let's settle that here; your tests are useful either way and could be carried over.
- (blocking) In
15-json-eof.t, the "premature EOF retains rejection in DetectionOnly" case asserts a 400 underSecRuleEngine DetectionOnly. That's existing behaviour (it was a 500), but DetectionOnly is expected not to block, and I'd rather not lock that in with a regression test. Please drop that case, or make it clear in the comment that it documents current, known-wrong behaviour that #2807 still tracks. - (non-blocking) To be clear on scope: completion errors still return before phase 2, so
REQBODY_ERRORrules (e.g. 200002 in the recommended config) and CRS never see these requests, and a customstatus:on the error rule is still ignored. That's fine for this PR, but it means #2807 stays open for the rule-controlled part. - (non-blocking) The per-case
test => subwrapper withno_yajl_statusis a lot of machinery for a no-YAJL build CI doesn't produce. Plain declarative cases alongside15-json.twould be simpler to maintain. - (non-blocking) Please squash. The first commit implements the approach you later dropped.
- (non-blocking) About the optional-build failure you mention in the description: if you think it has security impact, please send the details through the repository's private vulnerability reporting ("Report a vulnerability" under the Security tab) rather than this thread, and we'll take it from there.
Also, the Actions runs for this head never started (0 jobs). A new push will create fresh runs; if they fail to start again, we'll look at the workflow side.
59b1dfe to
9804b96
Compare
|
Thanks @fzipi. Updated in
Fresh isolated-container verification: 4,250 unit tests and 325 HTTP regressions pass for this revision. On the unchanged base with the new tests, 319/325 pass: exactly the six completion-status cases return 500 instead of 400, while all seven new controls pass. The separate refactor passes 4,250 unit tests and 336 HTTP regressions, including all 24 bucket tests. The new push created fresh Linux QA and IIS runs, but both currently report |
|
@coderabbitai review |
✅ Action performed
|
|
|
Thanks @vortexopenclaw for the quick and thorough update, and thanks @fzipi for the detailed review! First, I'd like to apologize: I should have spoken up much earlier. There are two older open PRs by @hnakamur that deal with request body handling when a limit is exceeded, and I'm only now pointing them out:
These overlap with this PR:
Since @hnakamur's PRs have been waiting longer and keep v2 and v3 consistent, I'd like to start with those: review #3483 and #3476 first, and merge them if they are OK. After that, I think this PR should be rebased on top of #3483, and the Regarding SonarCloud's Sorry again for the delay and for the extra round. Your tests are very useful either way, and I'd like to keep them. |







Summary
Return 400 Bad Request, rather than 500 Internal Server Error, when the built-in JSON parser fails during request-body completion. Preserve the existing early rejection; this is not a redesign of request-body error policy.
Following maintainer review, this PR is rebased onto
v2/masterat42b02c6b23a6c5ca3c8f067efd28097ae3a41935and squashed into one commit. The abandoned rule-controlled implementation is no longer in the PR history.Scope
-2for built-in JSON completion errors inmodsecurity_request_body_end().-2toHTTP_BAD_REQUESTinread_request_body(); retain-5→ 413 and other negative results → 500.15-json.t. These parser-specific assertions require YAJL; the per-case no-YAJL callback wrapper has been removed.10-request-buckets.tfrom this PR. They are now in v2: Separate request-body bucket handling from the reader #3716 and are not prerequisites for this fix.Remaining behavior and #2807
Completion failures still return before phase 2. Recommended-config rule 200002, other
REQBODY_ERRORrules, and CRS phase-2 rules do not see these requests; custom phase-2status:values remain ignored. In-stream JSON syntax errors still follow the existing rule-controlled path.DetectionOnly still rejects completion failures, which is known-wrong existing behavior, not a desired contract. The DetectionOnly regression case has been removed to avoid locking that behavior in. #2807 remains open for rule-controlled handling and DetectionOnly behavior. XML/multipart, unavailable JSON support, custom processors, storage failures and body-limit policies are unchanged.
Relationship to #3515: maintainer decision required
This JSON change adapts the JSON portion of Marc Stern's proposal in #3515; it is overlapping work, not an independent fix to merge alongside it. #3515 additionally changes XML/multipart handling.
My recommendation is to take this narrowly scoped JSON correction and its tests, and consider XML/multipart separately. If maintainers prefer #3515 instead, these tests can be carried over and this PR closed. Please choose one implementation path; do not merge both overlapping JSON changes. This recommendation does not resolve the maintainer decision by itself.
Verification of the revised commit
Ubuntu 24.04 arm64 container, Apache 2.4, YAJL enabled; container networking disabled and no published ports. Fresh source export of the revised commit, including the pinned libinjection submodule:
--enable-pcre-study=yes --enable-pcre-jit CFLAGS=-Werror=format-security.make test: 4,250/4,250 unit tests pass.Reproduce:
git submodule update --init --recursive ./autogen.sh ./configure --enable-pcre-study=yes --enable-pcre-jit CFLAGS=-Werror=format-security make -j4 make test make test-regressionThe actual HTTP runner in the root-owned isolated test container was
USER=root LOGNAME=root perl run-regression-tests.pl -S . -p 8090 -vfromtests/. SetUSER/LOGNAMEto the actual test-process user.These are current local results, not claims of current-head GitHub Actions success. Cross-platform CI and maintainer approval remain merge gates. Prior SonarCloud and CodeRabbit results applied to the superseded refactored head and do not establish this revision's status. No production deployment is included.
Optional-build investigation is separate from this standard-build status fix; any security-sensitive findings belong in private vulnerability reporting, not this public thread.