Security hardening and fix all compile warnings
Security fixes: - Validate theme background image URLs against whitelist pattern - Add board permission check to Socket.IO join-board handler - Disable raw HTML passthrough in markdown parser (XSS prevention) - Add UUID validation on avatar and branding route params (path traversal) - Add security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy) - Validate webhook URLs (HTTPS only, block internal addresses) - Add import payload size limit (5MB) - Remove server uptime from health endpoint - Make seed password configurable via SEED_ADMIN_PASSWORD env var - Patch DOMPurify dependency vulnerability via npm audit fix Warning fixes: - Convert $state(prop) to $effect.pre sync pattern (state_referenced_locally) - Add for/id pairings to form labels (a11y_label_has_associated_control) - Add svelte-ignore for intentional autofocus usage (a11y_autofocus) - Add ARIA roles to interactive/overlay divs (a11y_no_static_element_interactions) - Add aria-label to icon-only buttons (a11y_consider_explicit_label) - Add keyboard handler alongside click events (a11y_click_events_have_key_events) - Fix non-reactive fileInput declaration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import type { TenantThemeData } from '../../app.d.js';
|
||||
|
||||
/** Validates a theme background image URL is safe for CSS injection. */
|
||||
function isSafeCssUrl(url: string): boolean {
|
||||
return /^\/api\/branding\/[0-9a-f-]+\/[a-z-]+$/.test(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-side CSS variable mapping — mirrors server-side theme-css.ts
|
||||
*/
|
||||
@@ -77,16 +82,16 @@ export function persistThemeCSS(theme: TenantThemeData) {
|
||||
|
||||
// Handle background images
|
||||
const extraRules: string[] = [];
|
||||
if (theme.lightPageBgImage) {
|
||||
if (theme.lightPageBgImage && isSafeCssUrl(theme.lightPageBgImage)) {
|
||||
extraRules.push(`.layout-page-bg { background-image: url('${theme.lightPageBgImage}'); }`);
|
||||
}
|
||||
if (theme.lightNavBgImage) {
|
||||
if (theme.lightNavBgImage && isSafeCssUrl(theme.lightNavBgImage)) {
|
||||
extraRules.push(`.layout-nav-bg { background-image: url('${theme.lightNavBgImage}'); }`);
|
||||
}
|
||||
if (theme.darkPageBgImage) {
|
||||
if (theme.darkPageBgImage && isSafeCssUrl(theme.darkPageBgImage)) {
|
||||
extraRules.push(`html.dark .layout-page-bg { background-image: url('${theme.darkPageBgImage}'); }`);
|
||||
}
|
||||
if (theme.darkNavBgImage) {
|
||||
if (theme.darkNavBgImage && isSafeCssUrl(theme.darkNavBgImage)) {
|
||||
extraRules.push(`html.dark .layout-nav-bg { background-image: url('${theme.darkNavBgImage}'); }`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user