CNA-BUG-156: HttpNotificationChannel answers length-less, chunked and truncated pushes with 200 and reads request bodies of unbounded size
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
ReadRequestBody's comment says unreadable pushes are refused rather than delivered truncated, but a request without Content-Length gets 200 and is dropped, a short body gets 200 and is queued truncated, and the length is never bounded.
- Identifier
CNA-BUG-156- Category
- Bug
- Subsystem
- Networking & gamer services
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Phone::Notification::HttpNotificationChannel listener: the HTTP status a push sender receives and the bytes raised as HttpNotificationReceived
Expected behaviour
The comment above ReadRequestBody states the design: the channel “understands a request with a Content-Length and nothing else”, and chunked encoding and other forms “are not accepted rather than half-supported -- a push that this cannot read is better refused visibly than delivered truncated”. A sender should get an error status for a request the channel cannot read, and a raised notification should carry the whole body.
Actual behaviour at TARGET
ReadRequestBody reads until the blank line that ends the header block (a failed or closed connection, or a header block over 1 MiB, returns false and the worker answers 400). It then looks for content-length: anywhere in the lower-cased header block and parses it with strtoul; without it the length is 0. The body loop reads until that many bytes arrived or recv returns 0 or an error, and the function returns true either way. A request without Content-Length, including a chunked one, is therefore answered 200 OK and dropped (an empty body is never queued), and a peer that stops after fewer bytes than it declared gets 200 OK and its truncated body is queued and later raised. The declared length is never capped, so the worker's buffer grows with whatever a peer declares and sends.
Source locations
modules/phone/src/HttpNotificationChannel.cpp— ReadRequestBody (header loop, Content-Length search, body loop) and Listen (200/400 reply, queueing)modules/phone/tests/Microsoft/Phone/Notification/HttpNotificationChannelTests.cpp— only complete requests with a Content-Length are sent
Evidence
Checked by reading HttpNotificationChannel.cpp at 009d40f5; the file is unchanged since the earlier recorded pin. Not executed. The phone module's Development page already records the same response table as a maintainer note.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
HttpNotificationChannelTests.cpp (WhatAServicePostsArrivesAsANotification and the PushNotificationSenderTest cases) sends only complete requests with a Content-Length. No test sends a chunked, length-less, truncated or oversized request or reaches the 400 path.
Regression test
Four raw-socket cases against an open channel: a chunked body, a body without Content-Length, a body shorter than declared followed by a normal close, and a declared length above a fixed cap. Each must receive a 4xx status (411, 400, 400, 413) and queue nothing.
Blast radius
Pushes from senders other than CNA's own push sender, which always sends a Content-Length and the whole body; senders that fail mid-body; memory use of the listener thread. CNA-to-CNA pushes that complete are unaffected.
Workaround
Send pushes with a Content-Length and the complete body; a port can validate each payload (an expected length or checksum) in its handler.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Maintainer workflow
- Thread and callback map
- Known issues
- Bug index