Open Source API Gateway

400 Bad Request: XML Security Policy Violated

Membrane API Gateway returns 400 Bad Request with a link to this page when the xmlProtection plugin rejects an XML request body, or an XML part of a multipart body, because it is not well-formed or breaks the XML security policy. The request does not reach the backend.

The Error Response

The response contains the status 400 Bad Request, a detail that names the violation and, for parse errors, the line and column, the problem type https://membrane-api.io/problems/security and a link to this page. It also carries the header X-Protection: Content violates XML security policy. The type security means that a security plugin blocked the request.

What XML Protection Does

The xmlProtection plugin shields XML backends against attacks such as XML External Entities (XXE) and denial of service through huge or deeply nested documents. Read Protection Against XML Attacks and DoS for background.

api:
port: 2000
flow:
- xmlProtection:
maxAttributeCount: 1000
maxElementNameLength: 1000
maxAttributeNameLength: 1000
maxDepth: 50
maxSize: 10000000
removeDTD: true
target:
url: https://api.predic8.de
api:
  port: 2000
  flow:
    - xmlProtection:
        maxAttributeCount: 1000
        maxElementNameLength: 1000
        maxAttributeNameLength: 1000
        maxDepth: 50
        maxSize: 10000000
        removeDTD: true
  target:
    url: https://api.predic8.de

Common Causes

The Document Is Not Well-Formed

Tags are not closed, characters are not escaped, or the body ends before the document is complete. The detail contains the line and column of the error.

The Encoding Is Invalid

The XML declaration names an encoding that is invalid or not supported.

A Limit Is Exceeded

The document is larger than maxSize, is nested deeper than maxDepth, has an element with more attributes than maxAttributeCount, or has an element or attribute name longer than maxElementNameLength or maxAttributeNameLength. Namespace URIs are limited too.

An External Entity Is Declared

The DOCTYPE declares an external entity. This is a typical XXE attack and is always rejected.

An External DTD Is Referenced

The DOCTYPE references an external DTD while removeDTD is false. With removeDTD: true, the default, the DTD is removed and the request continues.

How to Fix It

  1. Client: send well-formed XML without a DOCTYPE, within the size and structure limits of the API.
  2. Operator: if legitimate documents are rejected, raise the specific limit named in the detail, for example maxSize or maxDepth.
  3. Operator: check the info-level log line Request was rejected by XML protection: ..., which contains the reason.

Hide Details in Production

By default, Membrane runs in development mode and adds details to error responses that help you find the problem. These details may reveal information about your setup. In production, turn them off:

configuration:
production: true
configuration:
  production: true

Add the configuration document to your apis.yaml and separate it from the APIs with ---.

Related Documentation

Configuration reference:

Tutorials with runnable examples:

← All Membrane error messages

Still stuck? See the troubleshooting guide or ask on GitHub Issues. For commercial support, contact info@predic8.de.