From 3a266e07ede28cab8ba48d1740f27937d00ba230 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Sun, 15 Mar 2026 00:11:10 +0100 Subject: [PATCH] fix: allow bare filenames in avatar/banner validation, fix password min length isValidAssetUrl() was rejecting bare filenames (e.g. "1234567890.webp") which is the established convention the frontend sends. Now accepts bare filenames while still blocking path traversal and unsafe schemes. Also updates client-side password validation to match server's 8-char minimum. --- packages/server/src/routes/users.ts | 4 +++- .../web/src/components/modals/settingsPanels/AccountPanel.tsx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/server/src/routes/users.ts b/packages/server/src/routes/users.ts index 535c4f54..1ce73adf 100644 --- a/packages/server/src/routes/users.ts +++ b/packages/server/src/routes/users.ts @@ -10,12 +10,14 @@ import { deleteUploadFile } from '../utils/fileCleanup.js'; import { tombstoneUser } from '../utils/userDeletion.js'; import { generateSnowflake } from '../utils/snowflake.js'; -/** Validates that a URL is a safe asset URL (relative upload path or http/https) */ +/** Validates that a URL is a safe asset URL (relative upload path, bare filename, or http/https) */ function isValidAssetUrl(url: string | null | undefined): boolean { if (!url || url.trim().length === 0) return true; // empty/null = clearing const trimmed = url.trim(); if (trimmed.startsWith('/api/uploads/')) return true; if (trimmed.startsWith('https://') || trimmed.startsWith('http://')) return true; + // Accept bare filenames (the existing convention) — no slashes, no traversal + if (!trimmed.includes('/') && !trimmed.includes('\\') && !trimmed.includes('..')) return true; return false; } diff --git a/packages/web/src/components/modals/settingsPanels/AccountPanel.tsx b/packages/web/src/components/modals/settingsPanels/AccountPanel.tsx index cde850c0..57bbe70d 100644 --- a/packages/web/src/components/modals/settingsPanels/AccountPanel.tsx +++ b/packages/web/src/components/modals/settingsPanels/AccountPanel.tsx @@ -214,8 +214,8 @@ export function AccountPanel() { setPasswordSuccess(''); setPasswordResults(null); - if (newPassword.length < 6) { - setPasswordError('New password must be at least 6 characters'); + if (newPassword.length < 8) { + setPasswordError('New password must be at least 8 characters'); return; } if (newPassword !== confirmNewPassword) {