Skip to content

Validate multipart boundary length against the RFC 2046 limit - #210

Merged
czechboy0 merged 2 commits into
apple:mainfrom
kukushechkin:multipart-boundary-limit
Sep 10, 2026
Merged

czechboy0 merged 2 commits into
apple:mainfrom
kukushechkin:multipart-boundary-limit

Conversation

@kukushechkin

Copy link
Copy Markdown
Contributor

Motivation

RFC 2046 section 5.1.1 limits a multipart/form-data boundary to at most
70 characters. requiredBoundary() currently returns the boundary from
the Content-Type header without checking its length, so a boundary of
any size is accepted and handed straight to the parser. Besides being out
of spec, an over-long boundary makes the parser's boundary matching do
more work than it should for no legitimate benefit — a well-formed request
never needs a boundary longer than the limit.

Modifications

  • Reject a boundary whose UTF-8 length exceeds 70 in requiredBoundary(),
    throwing a new RuntimeError.multipartBoundaryTooLong. Matching is done
    on UTF-8 bytes, consistent with how the parser consumes the boundary.
  • Map multipartBoundaryTooLong to a 400 Bad Request response, alongside
    the other malformed-Content-Type errors.
  • Add a unit test covering the boundaries at the limit (70, accepted) and
    just over it (71, rejected).

Result

Requests with a spec-compliant boundary decode exactly as before. A
boundary longer than 70 bytes is now rejected up front with a clear error
(surfaced as 400 Bad Request on the server path) instead of being passed
to the parser.

RFC 2046 section 5.1.1 limits a `multipart/form-data` boundary to at most
70 characters. `requiredBoundary()` currently returns the boundary from
the `Content-Type` header without checking its length, so a boundary of
any size is accepted and handed straight to the parser. Besides being out
of spec, an over-long boundary makes the parser's boundary matching do
more work than it should for no legitimate benefit — a well-formed request
never needs a boundary longer than the limit.

- Reject a boundary whose UTF-8 length exceeds 70 in `requiredBoundary()`,
throwing a new `RuntimeError.multipartBoundaryTooLong`. Matching is done
on UTF-8 bytes, consistent with how the parser consumes the boundary.
- Map `multipartBoundaryTooLong` to a `400 Bad Request` response, alongside
the other malformed-`Content-Type` errors.
- Add a unit test covering the boundaries at the limit (70, accepted) and
just over it (71, rejected).

Requests with a spec-compliant boundary decode exactly as before. A
boundary longer than 70 bytes is now rejected up front with a clear error
(surfaced as `400 Bad Request` on the server path) instead of being passed
to the parser.
@kukushechkin kukushechkin added the 🔨 semver/patch No public API change. label Sep 10, 2026

@czechboy0 czechboy0 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@czechboy0
czechboy0 merged commit b11e695 into apple:main Sep 10, 2026
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants