Overview
This release tightens the inbound HTTPU dispatcher and parser to RFC 9112 conformance, fixes several spec deviations in the Advertiser M-SEARCH responder, and exposes new options for explicit control over multicast inbound filtering and outbound advertisement.
Breaking changes
SSDP.Options.ttlis removed. The@gibme/multicast22.0.1 dependency hardcodesIP_MULTICAST_TTL=255per RFC 6762 outbound hardening; the field had become silently ignored. Consumers passingttlwill see a TypeScript error at compile time.- Default
AdvertiserUUID is now RFC 9562 v4 (was v7). UUID v7 encodes the device-creation ms timestamp in the first 48 bits, which was broadcast to every host on the multicast scope via everyUSNheader. If you need cross-reboot identity stability, generate a UUID once at install time, persist it, and pass it via theuuidoption.
New options
SSDP.Options.linkLocalOnly(defaultfalse). When true, drops inbound packets whose source is not on a local-link subnet. SSDP is not mDNS: RFC 6762 §11 normatively governs only the mDNS group, so the default keeps SSDP's traditional cross-subnet behavior. Single-segment deployments can opt into the stricter check.Advertiser.Options.silentMode(defaultfalse). When true, suppresses periodic multicastNOTIFY ssdp:aliveandssdp:byebyetraffic; the advertiser only answers unicastM-SEARCHrequests that passauthenticationProvider. Useful for pull-only / private-discovery deployments.
Dispatch and parser hardening
- The start-line of incoming datagrams is now matched exactly against three permitted shapes (
M-SEARCH * HTTP/1.1,NOTIFY * HTTP/1.1,HTTP/1.1 <status>). Garbage UDP no longer surfaces as a'reply'event with attacker-controlled headers. - Header parser rejects whitespace between field name and colon per RFC 9112 §5.1.
- Line splitting tolerates both
CRLFand bare-LF terminators. getHeader()now returns an empty string for present-but-empty headers, agreeing withhasHeader().- The
'drop'event from the underlying multicast layer is re-emitted bySSDPandBrowserso consumers have observability into packets filtered bylinkLocalOnly.
Advertiser semantics
- M-SEARCH responder now decides whether the target ST is one we advertise BEFORE calling
authenticationProvider. Unknown STs are silently dropped per SSDP convention instead of emitting an attacker-controllable error event. ssdp:allresponses now correctly includeupnp:rootdeviceanduuid:<UUID>in addition to each registered service.- Replies are now delayed by a random interval in
[0, MX]seconds per UPnP DA to mitigate the multicast reply-storm amplification. authenticationProviderthrows are caught and treated as a deny; the failure is surfaced via the'error'event instead of producing an unhandled promise rejection.- An empty-string
uuid(if explicitly passed) is replaced with a fresh v4 instead of falling open onuuid:matching.
CI / supply chain
- Pinned
s0/git-publish-subdir-actionto a verified commit SHA (was@develop). - Pinned
yarnto1.22.22in all install steps. - All workflows now use
yarn install --frozen-lockfile. - Restored the
npm install -g npm@latestupgrade in the publish job; Node 22.x ships npm 10.x which is too old for npm-CLI-side OIDC trusted publishing (requires npm 11.5.1+).
Packaging
package.json"types"field now points to./dist/index.d.ts(was./dist/index.ts, which is never emitted bytsc).
Tests
- Test suite expanded from 8 to 17 tests; adds regression coverage for parser, dispatcher, and Advertiser hardening.
- Dispatcher hardening tests reworked to use per-test marker-filtered assertions with positive-control packets, eliminating a multicast-loopback race that intermittently caused false failures on Windows runners when the suite-level advertiser's periodic NOTIFY frames landed inside the test window.
Security considerations
A new "Security Considerations" section in the README enumerates the SSDP threat model: the protocol has no authentication, the authenticationProvider gates unicast replies only (not outbound NOTIFY; use silentMode to suppress those), the random MX delay mitigates reply-storm amplification, and inbound parser hardening is documented.