fix(website): guard editor-supplied URLs against unsafe schemes
Menu items, button links, announcement bars, popups, floating buttons and
navbar CTAs all wrote editor-supplied values straight into href attributes.
Any user with settings.manage could store a `javascript:` URL and have it run
for every visitor of that tenant's public site.
Adds safe_url(), which allow-lists http/https/mailto/tel/whatsapp, site-relative
paths and fragments, and rejects protocol-relative URLs, data:, vbscript: and
entity/whitespace/control-character obfuscation before testing the scheme.
Applied at four layers so no writer can bypass it:
- input MenuManager rules + BlockField Link validation
- model WebsiteMenuItem::href()
- render every editor-supplied href in every website view
- import WebsiteBlueprintService, since blueprint files skip form rules
safe_url() returns null rather than '#', so blocks skip the link entirely
instead of emitting a dead anchor — this satisfies the project's no-href="#"
rule with the same mechanism.
Also fixes Alpine expression injection in the gallery and schedule lightboxes,
where a quote inside an image URL could break out of the inline handler: Blade
escapes ' to ' but the browser decodes it before Alpine parses.
Co-Authored-By:
Claude Opus 5 <noreply@anthropic.com>
Showing
Please register or sign in to comment