-
Notifications
You must be signed in to change notification settings - Fork 1.7k
v2: Allow partial processing of XML, JSON, and multipart request body #3483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v2/master
Are you sure you want to change the base?
v2: Allow partial processing of XML, JSON, and multipart request body #3483
Conversation
…ssing" Due to the previous change, the "no final boundary missing" error never occurs when SecRequestBodyLimitAction is ProcessPartial.
Adjust the expected error message to match the message changes introdueced in: owasp-modsecurity@dfbde55
But reject incomplete epilogue when body fits in limit.
|
Hi @hnakamur, thanks for this PR too.
I think and the payload: then the @dune73 what do you think?
How can we be sure that the payload is valid, if the error is in the chunked part? Eg. consider the config above and this JSON: {"a":1,"b":2,[1]]}(the second You helped me in #3456, which isn't merged yet (I'm waiting for a review and an approve). But could you add a new test case to the v2's source tree? |
|
Hello @airween. Thanks for your comment. I added tests for url-encoded, JSON, and XML request bodies. It appears that the URL-encoded parser already works as expected with By the way, I realized that it would be better to add more tests for multipart requests. I think it will take me a day or two to do so. |
This check is added to satisfy SonarQube Cloud Quality Gate on CI. owasp-modsecurity#3483 (comment)
To satisfy Quality Gate in CI. owasp-modsecurity#3483 (comment)
To satisfy Quality Gate in CI. owasp-modsecurity#3483 (comment)
5b38984 to
0bfb828
Compare
I was mistaken about that. I modified the URL-encoded parser to include names and values up to the delimiter before the limit when SecRequestBodyLimitAction is set to ProcessPartial and the request body exceeds SecRequestBodyLimit. I also modified the multipart parser to include parts whose boundary appears before the limit under the same conditions. In addition, I added tests to cover these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request fixes a bug where SecRequestBodyLimitAction ProcessPartial would cause parse errors when the request body exceeded the configured limit for XML, JSON, and multipart content types. The implementation enables parsers to gracefully handle truncated bodies by allowing partial/ill-formed data when the limit is exceeded.
Changes:
- Added
modsecurity_request_body_enable_partial_processing()function to enable partial processing for different body processors - Modified XML, JSON, multipart, and URL-encoded parsers to handle partial data when the limit is exceeded
- Added comprehensive test coverage for partial processing across all supported content types
- Changed request body limit comparison from
>=to>to correctly allow bodies exactly at the limit
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| apache2/apache2_io.c | Modified to truncate buffers at limit and enable partial processing mode |
| apache2/msc_reqbody.c | Added function to enable partial processing per processor type |
| apache2/modsecurity.h | Added field and function declaration for partial processing |
| apache2/msc_json.c | Fixed indentation and enabled yajl partial value parsing |
| apache2/msc_json.h | Added function declaration for JSON partial processing |
| apache2/msc_xml.c | Modified to skip well-formed checks when partial processing enabled |
| apache2/msc_xml.h | Added flag to allow ill-formed XML in partial mode |
| apache2/msc_multipart.c | Enhanced boundary handling for partial multipart bodies |
| apache2/msc_multipart.h | Added flag for partial multipart processing |
| apache2/msc_parsers.c | Modified URL-encoded parser to skip final parameter in partial mode |
| tests/regression/rule/15-json.t | Added 6 test cases for JSON partial processing |
| tests/regression/rule/10-xml.t | Added 3 test cases for XML partial processing |
| tests/regression/config/10-request-directives.t | Added extensive multipart, JSON, XML, and URL-encoded partial processing tests |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT) { | ||
| if (rcbe == -5) { | ||
| return HTTP_REQUEST_ENTITY_TOO_LARGE; | ||
| } | ||
| if (rcbe < 0) { | ||
| return HTTP_INTERNAL_SERVER_ERROR; | ||
| } | ||
| } |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling logic has been modified to only return error codes when if_limit_action is REQUEST_BODY_LIMIT_ACTION_REJECT. However, this means that when if_limit_action is REQUEST_BODY_LIMIT_ACTION_PARTIAL, errors from modsecurity_request_body_end (rcbe) are silently ignored and APR_SUCCESS is returned. This could mask legitimate parsing errors that occur during partial processing. Consider returning errors for non -5 error codes even in ProcessPartial mode.
| if (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT) { | |
| if (rcbe == -5) { | |
| return HTTP_REQUEST_ENTITY_TOO_LARGE; | |
| } | |
| if (rcbe < 0) { | |
| return HTTP_INTERNAL_SERVER_ERROR; | |
| } | |
| } | |
| /* Handle request body processing result: | |
| * - rcbe == -5: body too large -> 413 only in REJECT mode, ignore otherwise. | |
| * - other rcbe < 0: treat as internal error in all modes. | |
| */ | |
| if (rcbe == -5) { | |
| if (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT) { | |
| return HTTP_REQUEST_ENTITY_TOO_LARGE; | |
| } | |
| } else if (rcbe < 0) { | |
| return HTTP_INTERNAL_SERVER_ERROR; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change causes a parser error returns a response with status code 500, which is not wanted since this case is not an internal server error.
In case of a parse error, REQBODY_ERROR is set to 1, which can be used by a rule to return a 400 Bad Request response, for example:
SecRule REQBODY_ERROR "!@eq 0" "id:'200001', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
Side note: However, I found that no rule in OWASP CRS 4.22.0 checks REQBODY_ERROR.
This is wanted behavior for both of REQUEST_BODY_LIMIT_ACTION_REJECT and REQUEST_BODY_LIMIT_ACTION_PARTIAL.
Therefore I think the right modification here is:
if (rcbe == -5 && msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT) {
return HTTP_REQUEST_ENTITY_TOO_LARGE;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change causes a parser error returns a response with status code 500, which is not wanted since this case is not an internal server error.
okay, then we can make this as resolved. Thanks.
Side note: However, I found that no rule in OWASP CRS 4.22.0 checks
REQBODY_ERROR.This is wanted behavior for both of
REQUEST_BODY_LIMIT_ACTION_REJECTandREQUEST_BODY_LIMIT_ACTION_PARTIAL.
Good advice - would you mind to open a PR or just an issue under coreruleset?
Therefore I think the right modification here is:
if (rcbe == -5 && msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT) { return HTTP_REQUEST_ENTITY_TOO_LARGE; }
Do you want to add/change this one too? I'm waiting for your response, until that I don't resolve this comment.
| SecDebugLogLevel 9 | ||
| SecRequestBodyAccess On | ||
| SecRequestBodyLimitAction ProcessPartial | ||
| SecRequestBodyLimit 59 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, please add here and all other tests where you check the limit(s) the SecRequestBodyNoFilesLimit.
I think that would be useful to avoid the unwanted side effects (eg. not the relevant settings applied and a negative test is successed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before adding tests for SecRequestBodyNoFilesLimit, let me understand it for ProcessPartial.
Though the document for SecRequestBodyNoFilesLimit does not mention for ProcessPartial case, I believe we should not reject a request whose length exceeds the SecRequestBodyNoFilesLimit for ProcessPartial case. Is this correct?
And I found the current implemention is handling the request whose length exceeds SecRequestBodyNoFilesLimit inconsistently between modsecurity_request_body_store and modsecurity_request_body_end.
I fixed it at hnakamur@96a8326.
Could you take a look?
Should I include this commit to this pull request or should I create another pull request for SecRequestBodyNoFilesLimit?
I'll add tests for SecRequestBodyNoFilesLimit after the above fix is settled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before adding tests for
SecRequestBodyNoFilesLimit, let me understand it forProcessPartial.
Right, thanks.
Though the document for SecRequestBodyNoFilesLimit does not mention for
ProcessPartialcase, I believe we should not reject a request whose length exceeds theSecRequestBodyNoFilesLimitforProcessPartialcase. Is this correct?
Well, that's a good question.
@dune73 what do you think?
And I found the current implemention is handling the request whose length exceeds
SecRequestBodyNoFilesLimitinconsistently betweenmodsecurity_request_body_storeandmodsecurity_request_body_end.I fixed it at hnakamur@96a8326. Could you take a look?
Let me take a look at this soon.
Should I include this commit to this pull request or should I create another pull request for
SecRequestBodyNoFilesLimit?
It would be great if you merge the current v2/master branch into your working branch. Then after each commit the whole regression test will run, then we can see the tests are passed.
I'll add tests for
SecRequestBodyNoFilesLimitafter the above fix is settled.
Okay. I'll let you know if I'm done. Thanks.
| SecDebugLogLevel 9 | ||
| SecRequestBodyAccess On | ||
| SecRequestBodyLimitAction ProcessPartial | ||
| SecRequestBodyLimit 58 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the SecRequestBodyNoFilesLimit too with an exact value.
| SecDebugLogLevel 9 | ||
| SecRequestBodyAccess On | ||
| SecRequestBodyLimitAction ProcessPartial | ||
| SecRequestBodyLimit 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the SecRequestBodyNoFilesLimit with an exact value.
In these cases (where you check non-multipart requests) could you add more tests with higher SecRequestBodyLimit values?
|
Hi @hnakamur, thank you again for your work, I think this is a very important fix. Please take a look at GH Copilot review, there are a logic change and a typo in the code. I also added a few notices to tests. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1ea8ee9 to
da8b174
Compare
|



what
SecRequestBodyLimitActionis set toProcessPartialand the length of an XML or JSON request body exceeds the configured limit.why
SecRequestBodyLimitActionisProcessPartial, the expected behavior is to process the partial XML, JSON, or multipart body up to the defined limit.references
The same modification for v3 is at: #3476