diff --git a/tradein-mvp/frontend/src/app/page.tsx b/tradein-mvp/frontend/src/app/page.tsx index 2d8e49a8..df6e7058 100644 --- a/tradein-mvp/frontend/src/app/page.tsx +++ b/tradein-mvp/frontend/src/app/page.tsx @@ -58,8 +58,15 @@ export default function TradeInPage() { useEffect(() => { const root = document.documentElement; if (!brand) return; - root.style.setProperty("--accent", brand.primary_color); // зелёный (бренд) - root.style.setProperty("--accent-2", brand.accent_color); // циан (акцент) + // Бренд-цвета идут в CSS custom-property без доверия (#766: подменённый бренд + // → CSS-инъекция). Применяем только валидный hex / rgb()/hsl(); иначе дефолт. + const COLOR_RE = /^#[0-9a-fA-F]{3,8}$|^(rgb|hsl)a?\([\d.,%\s/]+\)$/; + if (COLOR_RE.test(brand.primary_color)) { + root.style.setProperty("--accent", brand.primary_color); // зелёный (бренд) + } + if (COLOR_RE.test(brand.accent_color)) { + root.style.setProperty("--accent-2", brand.accent_color); // циан (акцент) + } root.classList.add("brand-active"); return () => { root.style.removeProperty("--accent"); diff --git a/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx b/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx index a2737747..8bdec5bf 100644 --- a/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx @@ -5,6 +5,7 @@ import { UserMenu } from "@/components/auth/UserMenu"; import { API_BASE_URL, HTTPError } from "@/lib/api"; import { isPathAllowed } from "@/lib/isPathAllowed"; +import { safeUrl } from "@/lib/safeUrl"; import { useBrand } from "@/lib/useBrand"; import { useMe } from "@/lib/useMe"; @@ -94,9 +95,19 @@ export function Topbar({ active }: TopbarProps) {
- {brand?.logo_url ? ( + {brand ? ( <> - {brand.name} + {/* logo_url из бренд-конфига → safeUrl (блок javascript:/data: схем, #766). + Невалидный URL → fallback на TI-марку, без broken/опасного img. */} + {safeUrl(brand.logo_url) ? ( + {brand.name} + ) : ( + TI + )} {brand.name} ) : (