Files
mercadodevida/work/artifacts/F-077/architect.md
2026-08-19 19:33:26 +02:00

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 renderHtml helper 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)} with renderHtml(p.description ?? '').slice(0, 60) using dangerouslySetInnerHTML
    • Truncate the sanitized HTML string to 60 chars (keeping HTML tags if within the limit)

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, '&lt;iframe')
    .replace(/<object/gi, '&lt;object')
    .replace(/<embed/gi, '&lt;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 --noEmit admin
  • npx eslint on changed file
  • ./scripts/verify.sh green
  • Manual: check a product with HTML in description renders formatted text in product listing