fix(site): cap the sign-up body by bytes read, not Content-Length #155

Merged
ryangr0 merged 1 commit from ryangr0/site-signup-byte-cap into development 2026-10-03 00:30:15 +00:00 AGit
Owner

The sign-up handler compared the Content-Length header to the 8 KiB limit,
treated a missing header as zero and then parsed the unbounded body with
request.formData(). A 65,610-byte form sent without the header was accepted
and stored.

The body is now read through a byte-counting reader that cancels the stream
and answers 413 as soon as it passes MAX_BODY_BYTES, before D1 is touched.
The form is parsed from the bytes that were read. Content-Length remains only
as an early rejection when it already declares a body over the limit.

Refs: VIK-1720

Co-Authored-By: Claude Opus 5.5 (1M context) noreply@anthropic.com

Content-Length is now only an early rejection; the body is counted as it streams and the stream is cancelled past 8 KiB. The form is parsed from the bytes read with the request's own Content-Type, so multipart boundaries still work.

Verified with mise run verify on the pinned toolchain (all gates passed).

Ticket: https://vikunja.webgrip.dev/tasks/1720

🤖 Generated with Claude Code

The sign-up handler compared the Content-Length header to the 8 KiB limit, treated a missing header as zero and then parsed the unbounded body with request.formData(). A 65,610-byte form sent without the header was accepted and stored. The body is now read through a byte-counting reader that cancels the stream and answers 413 as soon as it passes MAX_BODY_BYTES, before D1 is touched. The form is parsed from the bytes that were read. Content-Length remains only as an early rejection when it already declares a body over the limit. Refs: VIK-1720 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Content-Length is now only an early rejection; the body is counted as it streams and the stream is cancelled past 8 KiB. The form is parsed from the bytes read with the request's own Content-Type, so multipart boundaries still work. Verified with `mise run verify` on the pinned toolchain (all gates passed). Ticket: https://vikunja.webgrip.dev/tasks/1720 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(site): cap the sign-up body by bytes read, not Content-Length
Some checks failed
[Workflow] On Pull Request / checks (pull_request) Successful in 3m0s
[Workflow] On Pull Request / release-policy (pull_request) Failing after 19s
[Workflow] On Pull Request / warnings (pull_request) Successful in 0s
4769b7a35c
The sign-up handler compared the Content-Length header to the 8 KiB limit,
treated a missing header as zero and then parsed the unbounded body with
request.formData(). A 65,610-byte form sent without the header was accepted
and stored.

The body is now read through a byte-counting reader that cancels the stream
and answers 413 as soon as it passes MAX_BODY_BYTES, before D1 is touched.
The form is parsed from the bytes that were read. Content-Length remains only
as an early rejection when it already declares a body over the limit.

Refs: VIK-1720

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ryangr0 merged commit 33b54bfd82 into development 2026-10-03 00:30:15 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
webgrip/unfold!155
No description provided.