You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Restrict avatar/logo URL schemes at write time (template-context hardening) #103
AvatarURL, LogoURL and similar branding values flow into rendered templates (including the public directory pages). No javascript:/data:-URL rejection was found at the settings/upload layer. html/template neutralizes javascript: in URL attribute contexts, but only if each template places these values in a URL context (vs a CSS/style context, where escaping rules differ). This pass verified the Go side only, not every template insertion point.
Fix
Confirm directory.html and the booking templates put avatar/logo only in src/href attribute contexts.
Restrict stored avatar/logo URLs to http(s) plus relative paths at write time (defense in depth, independent of template context).
Also confirmed in the same pass: GET /v1/bookings/{id} (internal/server/server.go:454) is registered without auth or rate limit, unlike every neighboring route. IDs are UUIDv4 so enumeration is infeasible, and the response omits attendee PII, but any leaked ID discloses that booking's times, status and location_value with no token. Harden by requiring the manage token or rate-limiting. Tracking here to keep it with the audit batch; split out if preferred.
Found by the 0.10.1 pre-release audit (Layer 2, SSRF + isolation passes).
Both parts addressed, one with code and one with verification:
Avatar/logo schemes: verified safe, no change. Every insertion point (directory.html, book.html, manage.html) puts these values in src="..." attribute contexts only, where html/template neutralizes javascript: URLs. And there is no free-text URL write path to restrict: logo/banner come solely from file uploads (server-generated relative paths), avatars solely from uploads (/avatars/<id>) plus NULL-clearing - no OAuth picture URLs, no pasted-URL fields anywhere. Validating server-generated paths would be theater, so the defense here is the template contexts, now confirmed by inspection.
GET /v1/bookings/{id}: rate-limited, contract kept. It stays public (deliberate - UUIDv4 IDs are not enumerable, no attendee PII in the response, and external API consumers may rely on it), but it now sits behind the same 20/min booking limiter as booking creation instead of unlimited. Auth-gating would have been stronger but breaks the public contract; the limiter bounds leaked-ID probing to irrelevance.
Activity
pullfrog commentedon Sep 29, 2026
shockalotti commentedon Sep 29, 2026
Both parts addressed, one with code and one with verification:
Avatar/logo schemes: verified safe, no change. Every insertion point (directory.html, book.html, manage.html) puts these values in
src="..."attribute contexts only, wherehtml/templateneutralizesjavascript:URLs. And there is no free-text URL write path to restrict: logo/banner come solely from file uploads (server-generated relative paths), avatars solely from uploads (/avatars/<id>) plus NULL-clearing - no OAuth picture URLs, no pasted-URL fields anywhere. Validating server-generated paths would be theater, so the defense here is the template contexts, now confirmed by inspection.GET /v1/bookings/{id}: rate-limited, contract kept. It stays public (deliberate - UUIDv4 IDs are not enumerable, no attendee PII in the response, and external API consumers may rely on it), but it now sits behind the same 20/min booking limiter as booking creation instead of unlimited. Auth-gating would have been stronger but breaks the public contract; the limiter bounds leaked-ID probing to irrelevance.
fix(api): rate-limit public GET booking by ID (#103)
chore(audit): re-verify claims manifest after 0.10.x changes
docs(changelog): 0.10.1 notes for #103-106 (rate limit, CalDAV oracle…