2.2 KiB
2.2 KiB
F-077 — Architect: Product short description renders HTML in admin product list
Problem
The admin product listing (/products) renders p.description as plain text using {p.description?.slice(0, 60)}. If the description contains HTML tags (e.g., from a rich text editor), they are displayed as raw text (e.g., <strong>Fresh</strong>) instead of being rendered as formatted HTML.
Goal
Render HTML in the brief description field safely (without XSS risk).
Scope IN
project/apps/admin/src/app/(dashboard)/products/page.tsx:- Add a
renderHtmlhelper function that strips dangerous tags (script, onclick, onerror, etc.) while preserving safe formatting tags (b, i, em, strong, br, p, etc.) - Replace
{p.description?.slice(0, 60)}withrenderHtml(p.description ?? '').slice(0, 60)usingdangerouslySetInnerHTML - Truncate the sanitized HTML string to 60 chars (keeping HTML tags if within the limit)
- Add a
Scope OUT
- No new dependencies (simple regex-based sanitization)
- No changes to the backend or database
- No changes to other pages
Design
/** Renders HTML safely: strips dangerous tags (script, onclick, onerror, etc.)
* while preserving safe formatting tags (b, i, em, strong, br, p, etc.) */
function renderHtml(html: string): string {
if (!html) return '';
return html
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/\son\w+="[^"]*"/gi, '')
.replace(/\son\w+='[^']*'/gi, '')
.replace(/javascript:/gi, '')
.replace(/<iframe/gi, '<iframe')
.replace(/<object/gi, '<object')
.replace(/<embed/gi, '<embed');
}
In the product row:
<p
className="text-xs text-gray-400 truncate max-w-xs"
dangerouslySetInnerHTML={{
__html: renderHtml(p.description ?? '').slice(0, 60),
}}
/>
This renders <strong>Fresh</strong> as Fresh (bold) instead of literal text.
Risk
- Low risk: purely frontend rendering change, no backend or DB changes
- Sanitization removes dangerous tags but allows safe formatting HTML
Verification
npx tsc --noEmitadminnpx eslinton changed file./scripts/verify.shgreen- Manual: check a product with HTML in description renders formatted text in product listing