Security patch release. All four fixes below are included.
- Guard outbound fetches (
/bookmark,/import) against SSRF: reject loopback,
RFC1918/CGNAT, and link-local (incl. cloud metadata) targets on every
connection and redirect hop, plus a scheme check. Escape hatch:
ATOMIC_ALLOW_PRIVATE_FETCH=1. Reported by Ray Sabee / Whitehat Security
(@raysabee). - Close two bugs undermining the single-use guarantee of the bootstrap
/setupinvite: an inverted expiry check that rejected valid invites and
let expired ones through, and a TOCTOU race onusagesLeftthat let
concurrent requests both redeem what's meant to be a single-use invite.
Reported by @luuhung1217. - Block arbitrary file read via
internalId: a signed Commit could set this
server-managed property directly, and/downloadtrusted it verbatim as a
filesystem path (traversal / absolute path).internalIdis now denied in
externally-submitted commits, and/downloadindependently sanitizes and
confines the resolved path to the uploads directory. GHSA-8vc4-8hjq-988p,
reported by @luuhung1217. - Prevent stored XSS via uploaded files:
/downloadnow forces
Content-Disposition: attachmentandX-Content-Type-Options: nosniff, so
an uploaded HTML/SVG file can no longer render inline in the app's own
origin. GHSA-x277-3wcg-g9r2, reported by @luuhung1217