Skip to content

XML body processor: surface libxml2's parse error in REQBODY_ERROR_MSG and the debug log #3678

Open

Description

@fzipi

What

When the XML request body processor fails, the only diagnostic a user gets is the fixed string XML: Failed to parse document. in REQBODY_ERROR_MSG (and the matching [data "..."] of rule 200002). libxml2 knows exactly what went wrong, for example Extra content at the end of the document or Opening and ending tag mismatch: book line 1 and bookasdf, with line and column, but we discard it.

Until 3.0.15 that detail leaked to stderr by accident. #3677 silences it properly, so from now on it is lost entirely.

Proposal

After a failed xmlParseChunk() in src/request_body_processor/xml.cc, read xmlCtxtGetLastError(ctx) and, when it returns non-null, build the error string from its message, line and int2 (column) fields instead of the fixed text:

XML: Failed to parse document: Extra content at the end of the document (line 1, column 13)

Apply the same to the _arg context (Failed to parse document for ARGS.). Keep the fixed text as the fallback when xmlCtxtGetLastError() returns null or an empty message.

xmlCtxtGetLastError() is available and non-deprecated in every libxml2 release we build against (checked 2.9.13 and 2.15.4). The 2.15 headers state that errors remain accessible through it when XML_PARSE_NOERROR is set, so this works on top of #3677 with no LIBXML_VERSION conditionals and no SAX or structured-error callback.

Why

  • Operators debugging rule 200002 hits today have to reproduce the request with the body captured, which several reporters on REQBODY_ERROR "Extra content at the end of the document" after 3.0.15 update #3563 could not do for PCI reasons. The libxml2 message alone often tells them whether it was a truncated body, a wrong Content-Type, or a genuine probe.
  • Rule writers can match on REQBODY_ERROR_MSG to treat, say, Document is empty differently from a tag mismatch.
  • The message is libxml2's own text, which is what the stderr line used to show, so no new information is exposed beyond what 3.0.15 and 3.0.16 already printed.

Things to decide

  • Whether to trim the message to a fixed length. libxml2 messages are short, but message can embed element names from the body.
  • Whether the new text goes only into the debug log at level 4 or also into REQBODY_ERROR_MSG. The proposal above says both, since the variable is where rule writers can act on it.
  • Whether @validateSchema and @validateDTD should get the same treatment. They are separate code paths (src/operators/validate_schema.cc, validate_dtd.cc) and currently use their own error callbacks; out of scope here unless someone wants it.

Test

Extend test/test-cases/regression/variable-REQBODY_PROCESSOR_ERROR.json (or add a sibling) with a rule that matches REQBODY_ERROR_MSG against @contains Opening and ending tag mismatch, so the message content is asserted, not just that an error occurred.

References

Follow-up to #3563 and #3677. Related: #3455.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions