fix(tradein): санитизация brand.logo_url + валидация brand-цветов (#766) #791
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#791
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/766-brand-sanitize"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary (security, чейн с #765)
brand.logo_urlобёрнут вsafeUrl(блокируетjavascript:/data:/прочие не-http(s) схемы). Невалидный URL → fallback наTI-марку (без broken/опасного<img>),brand.nameсохраняется.primary_color/accent_colorвалидируются regex (hex/rgb()/hsl()) передsetProperty— невалидный цвет не применяется (остаётся дефолт), защита от CSS-инъекции подменённым бренд-конфигом.Why
Бренд-поля рендерились без санитизации; в чейне с
?brand=override (#765) подменённый бренд был вектором дляjavascript:-URL в логотипе / CSS-инъекции в цветах.Test plan
npx tsc --noEmit→ 0 ошибокnpm run build→ ✓ Compiled successfully, 10/10 pagesgrep safeUrl Topbar.tsx→ ≥1;grep 'test(' page.tsx→ 2 (оба цвета под guard)javascript:-logo → TI-марка (qa)Refs #766
✅ APPROVE
Frontend brand-санитизация (security, чейн #765/#766, frontend-двойник #789 part D).
Correctness
brand.logo_url→safeUrl(...); валидный → img, иначе fallback<span>TI</span>(brand.name сохранён). Блокjavascript:/data:/non-http(s).COLOR_RE = /^#[0-9a-fA-F]{3,8}$|^(rgb|hsl)a?\([\d.,%\s/]+\)$/гейтитsetProperty; char class исключает;{}:→ CSS-инъекция (напр.red;}body{…) не матчится. Только hex + rgb/hsl(a). Невалид → дефолт. Корректно.test()guard).Advisory (non-blocking) — (1)
safeUrl(brand.logo_url)вызывается дважды в Topbar (косметика, чистая fn); (2) frontend использует только scheme-block vs domain-allowlist в PDF #789 — достаточно для client-side img XSS (нет SSRF в браузере), domain-allowlist совпал бы со строгостью PDF (опц. follow-up).Scope/security — page.tsx + Topbar.tsx; переиспользует existing safeUrl, нет backend, нет secrets, нет self-extending триггера. P3.
Verdict: ✅ APPROVE (#766). Smoke (praktika logo+цвета; javascript:-logo → TI) → qa.