Skip to content
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

fix(http): send minimal end multipart boundary #6661

Open
wants to merge 1 commit into
base: v1.x
Choose a base branch
from

Conversation

igstan
Copy link

@igstan igstan commented Oct 21, 2024

I've bumped into an issue where Azure's Web Application Firewall (an L7 firewall) was blocking multipart/form-data requests sent by Axios with the message: "Multipart request body failed strict validation". There wasn't much info otherwise, so debugging this took me a while.

It turned out that the problem is an extra CRLF sequence that Axios adds at the end of the request body, which is allowed by the standard, but disallowed by Azure. This commit removes that extra final CRLF, which renders Axios interoperable with Azure's strict WAF policies, while keeping the code standards-compliant.

What follows below is the technical explanation, taken from the commit itself.


See: https://datatracker.ietf.org/doc/html/rfc2046#section-5.1.1

RFC 2046, §5.1.1, says that a multipart body ends with a single, optional CRLF sequence, and that extra data (the epilogue) is allowed, but should be ignored by receiving agents:

   multipart-body := [preamble CRLF]
                    dash-boundary transport-padding CRLF
                    body-part *encapsulation
                    close-delimiter transport-padding
                    [CRLF epilogue]

   close-delimiter := delimiter "--"

   transport-padding := *LWSP-char
                        ; Composers MUST NOT generate
                        ; non-zero length transport
                        ; padding, but receivers MUST
                        ; be able to handle padding
                        ; added by message transports.

   epilogue := discard-text

   discard-text := *(*text CRLF) *text
                   ; May be ignored or discarded.

Note that the end is signaled by close-delimiter, followed by transport-padding and an optional CRLF and epilogue.

Now, in theory we need not send even the first CRLF (although most clients and servers expect it, so we have to keep it), but the second CRLF sequence is more than extraneous.

However, that second CRLF becomes problematic with some middleware. For example, the Azure Web Application Firewall has strict rules when it comes to the epilogue section and will block requests if it detects anything there. This is not standards-compliant, but given that we don't have to send two CRLF terminators anyway, we can continue being standards-compliant while allowing our users to access WAF-protected websites.

See: https://datatracker.ietf.org/doc/html/rfc2046#section-5.1.1

RFC 2046, §5.1.1, says that a multipart body ends with a single, optional CRLF
sequence, and that extra data (the epilogue) is _allowed_, but should
be _ignored_ by receiving agents:

```
   multipart-body := [preamble CRLF]
                    dash-boundary transport-padding CRLF
                    body-part *encapsulation
                    close-delimiter transport-padding
                    [CRLF epilogue]

   close-delimiter := delimiter "--"

   transport-padding := *LWSP-char
                        ; Composers MUST NOT generate
                        ; non-zero length transport
                        ; padding, but receivers MUST
                        ; be able to handle padding
                        ; added by message transports.

   epilogue := discard-text

   discard-text := *(*text CRLF) *text
                   ; May be ignored or discarded.
```

Note that the end is signaled by `close-delimiter`, followed by
`transport-padding` and an optional CRLF and epilogue.

Now, in theory we need not send even the first CRLF (although most clients and
servers expect it, so we have to keep it), but the second CRLF sequence is
more than extraneous.

However, that second CRLF becomes problematic with some middleware. For
example, the Azure Web Application Firewall has strict rules when it comes to
the epilogue section and will block requests if it detects anything there.
This is not standards-compliant, but given that we don't have to send two CRLF
terminators anyway, we can continue being standards-compliant while allowing
our users to access WAF-protected websites.
@igstan igstan marked this pull request as ready for review October 21, 2024 19:01
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