Skip to content

v2: surface libxml2's parse error in REQBODY_ERROR_MSG and silence its stderr output - #3681

Open
fzipi wants to merge 2 commits into
owasp-modsecurity:v2/masterfrom
fzipi:v2/issue-3680-xml-errors
Open

fzipi wants to merge 2 commits into
owasp-modsecurity:v2/masterfrom
fzipi:v2/issue-3680-xml-errors

Conversation

@fzipi

@fzipi fzipi commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

what

v2 counterpart of #3677 and #3679, in two commits:

  1. Surface libxml2's parse error. REQBODY_ERROR_MSG and the logs now carry libxml2's own reason with line and column instead of the fixed XML: Failed to parse document.:
    XML parser error: XML: Failed to parse document: Opening and ending tag mismatch: book line 3 and bookasdf (line 6, column 12)
    
    After a failed xmlParseChunk(), xmlCtxtGetLastError() is read and the message built from its message, line and int2 fields (trailing newline trimmed, passed through log_escape_nq()). The fixed text stays as the fallback. Same for the ARGS context. In xml_complete() the error is read before xmlFreeParserCtxt(). The dead xml_receive_sax_error() under #if 0, which was the original design for this, is replaced by the new helper.
  2. XML_PARSE_NOERROR | XML_PARSE_NOWARNING on both parser contexts, set through xmlCtxtUseOptions() so it applies on every libxml2 version (OR-ing ctx->options directly is a no-op before 2.13, see fix: silence libxml2 parser errors on every libxml2 version #3677).

why

See #3680. Operators debugging XML body failures could not tell a truncated body from a wrong Content-Type or a probe without capturing the body.

One correction to the issue text: I claimed libxml2's body.xml:N: parser error lines reach Apache's error log. Under Apache 2.4 worker MPM with libxml2 2.9.14 I could not observe them even before this change, although httpd's stderr is the error log. So for the Apache module the flag is parity with v3 rather than a measured fix. The connector-based v3 report (#3563) did show the lines with nginx.

Not changed here: a v2 XML parse failure still answers HTTP 500 from read_request_body() before phase 2 runs, so a rule on REQBODY_ERROR_MSG cannot act on it yet. That is the same shape as the multipart change in #3658 and should be decided together with it.

tests

New tests/regression/target/10-variable-reqbody_error_msg-xml.t (auto-discovered): a tag-mismatch body and the <xml></xml> Testing modsec body from #3563, each asserting the libxml2 text in the error log and the absence of libxml2's own stderr lines. Both fail on v2/master (error log only has the fixed string) and pass with commit 1.

Verified in an Ubuntu 24.04 container (apache2 2.4.58, libxml2 2.9.14, --without-lua):

  • the new file and rule/10-xml.t pass;
  • full make test-regression: 296/309, the 13 failures are all environmental (12 use SecRuleScript with no Lua built, SecDataDir writes an SDBM file on a virtiofs mount) and reproduce without this change.

references

Fixes #3680. v3: #3677, #3679. Background: #3563, #3678.

🤖 Generated with Claude Code

fzipi and others added 2 commits October 13, 2026 12:10
When the XML body processor fails, REQBODY_ERROR_MSG and the logs only
said "XML: Failed to parse document." libxml2 knows the actual reason
(tag mismatch, extra content after the root element, empty document,
...) with line and column, but it was discarded. The dead
xml_receive_sax_error() under #if 0 was the original design for this.

Read xmlCtxtGetLastError() after a failed xmlParseChunk() and build the
message from it:

    XML: Failed to parse document: Opening and ending tag mismatch:
    book line 3 and bookasdf (line 6, column 12)

The fixed text stays as the fallback when libxml2 has no message. The
same applies to the ARGS parsing context. In xml_complete() the error
is read before xmlFreeParserCtxt(). xmlCtxtGetLastError() is available
since libxml2 2.6 and is not deprecated in 2.15.

Adds tests/regression/target/10-variable-reqbody_error_msg-xml.t with
a tag-mismatch body and the "extra content" body from v3 owasp-modsecurity#3563, both
asserting the libxml2 text in the error log.

Part of owasp-modsecurity#3680. v3 counterpart: owasp-modsecurity#3679.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Neither push parser context had XML_PARSE_NOERROR | XML_PARSE_NOWARNING,
so libxml2 was free to print its own "body.xml:N: parser error" lines
to stderr. Set them through xmlCtxtUseOptions(), which applies on every
libxml2 version; OR-ing ctx->options directly is a no-op before 2.13
(see v3 owasp-modsecurity#3563 / owasp-modsecurity#3677). The reason is still reported through
xmlCtxtGetLastError().

Note: under Apache 2.4 (worker MPM) with libxml2 2.9.14 no such stderr
lines were observed even before this change, so for the Apache module
this is parity with v3 rather than a measured fix.

Part of owasp-modsecurity#3680. v3 counterpart: owasp-modsecurity#3677.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 8d3534f6-46f7-4c42-99ae-1b16d1620457

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant