feat(widget): safely render Markdown images for product photos and payment QR
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 38/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- html, markdown, typescript
Línea de trabajo
Start by reading packages/dewee-webchat/src/widget/markdown.ts and the existing security expectations in packages/dewee-webchat/test/markdown.test.ts; these define the parser and the invariant that raw model-supplied HTML stays escaped. Then trace the public widget options and README to see where image-host configuration belongs, and inspect src/widget/styles.ts for responsive styling. Done means the acceptance criteria are covered by new tests in markdown.test.ts, with pnpm test, pnpm typecheck, and pnpm build passing.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Context
The current safe Markdown renderer in packages/dewee-webchat/src/widget/markdown.ts builds DOM nodes directly (no innerHTML), supporting text, links, tables, code blocks, etc., but does not parse the Markdown image syntax  into an actual image.
Verified on main at 42dfbc4628f45c2d006a2408a3b656a949680abb:
INLINE_SRCrecognizes[label](url)but has no image token; leading!is treated as plain text.renderInlinecreates<a>elements for safe links but never<img>.packages/dewee-webchat/test/markdown.test.tsexplicitly asserts that raw untrusted<img src=... onerror=...>must remain escaped. This is a security property to preserve, not a test to delete.packages/dewee-webchat/src/widget/styles.tshas no responsive Markdown image styles.
Why it matters
A Dewee sales agent using a Storefront MCP server should be able to show product images alongside names, prices, descriptions, and comparison tables. A Payment/SePay/VietQR MCP tool may return a payment QR image URL. Today, the chat can show image URLs as text/links but not render them natively in Markdown.
This issue covers safe Markdown image rendering (first usable step). Interactive product cards, product carousels, and a richer checkout/QR message component should be built later on a typed rich-message contract rather than embedding executable HTML in LLM output.
Requirements
1. Markdown image parsing and rendering
- Add support for
and relevant safe relative URLs while preserving existing text/link syntax. Nested/escaped syntax should be handled deliberately and covered by tests. - Create
<img>DOM elements withdocument.createElement, assignsrc/text safely, and never useinnerHTMLor arbitrary HTML supplied by the model. - Set
alt,loading="lazy",decoding="async"andreferrerPolicy="no-referrer"; avoid content jumping via sensible container sizing if feasible. - Product and payment QR images must fit the chat bubble on mobile and desktop, retain correct aspect ratio, and not overflow horizontally.
- Broken/rejected images should fall back gracefully to alt text or a safe clickable link.
2. Image URL trust/privacy policy
- Images are fetched by the visitor's browser; untrusted remote images can track visitor IPs or send requests to unexpected origins. Do not reuse
safeHrefunmodified as the image policy. - Reject unsafe schemes (
javascript:,data:,blob:,file:, etc.), protocol-relative URLs, control/obfuscated schemes, and suspicious inputs. Support approved HTTPS origins and safe same-origin URLs. - Provide a host-configurable image origin allowlist / opt-in for third-party images so a site's trusted Storefront CDN and payment-QR host can be explicitly approved; fail safely for unapproved sources.
- Never allow
onerror/event handlers, inline SVG, arbitrary HTML attributes, or user-supplied script. Consider SVG file/image handling explicitly in the threat model. - Apply the policy consistently to streamed replies, conversation history, inline widget mode, and floating mode.
3. Public API and styling
- Expose the required image-host configuration through the appropriate public widget options and wrappers (vanilla/script, React, Vue, Astro) without breaking existing options.
- Add styles in
src/widget/styles.tsfor responsive images, rounded corners, sensible max-size, and accessible alt/fallbacks. - Document the Markdown syntax, security policy, and how to allow a Storefront CDN or VietQR image host in the package README.
- Keep the bundle lightweight and do not add a large Markdown/HTML framework just for images.
4. Tests / acceptance criteria
- Valid trusted
renders an<img>with correct alt/source and privacy attributes when the host is allowed. - Valid QR image URL from an explicitly allowed payment origin displays without distortion.
- Plain links
[text](url), autolinks, fenced/inline code, bold/italic, tables, and lists still render as before. - An untrusted literal
<img src=x onerror=...>remains escaped and never becomes an image. - URLs with disallowed schemes, origins, malformed encoding, or injected attributes never lead to unsafe DOM nodes or outbound image fetches.
- Markdown image syntax inside code spans/fences stays literal.
- Failure/unavailable image has an accessible fallback; mobile widths do not overflow.
- Streaming / history rerenders have consistent behavior and do not duplicate nodes.
-
pnpm test,pnpm typecheck, andpnpm buildpass; add tests inpackages/dewee-webchat/test/markdown.test.tsand a widget-level regression test where useful.
Implementation approach
- Introduce a dedicated image token/parser branch that precedes link parsing, without sacrificing the renderer's current safe DOM construction.
- Centralize URL validation and widget host policy rather than relying on regex alone; normalize URLs using
URLand compare normalized origins against a site-owned allowlist. - Render with restricted attributes and CSS classes, then add coverage for adversarial inputs and view-mode parity.
- Document approved CDN/QR host examples as configuration placeholders, not hard-coded trusted services.
Explicit non-goals for this issue
- No direct integration with Storefront MCP, SePay, or VietQR API in this repository.
- No order creation, payment verification, checkout state changes, or business logic in the renderer.
- No arbitrary HTML/JS execution or generalized remote content embed.
- Typed
product_card,product_comparison,payment_qr/checkout components: propose separately once image support is stable.
References
- Lenguaje dominante
- TypeScript
- Estrellas
- 7
- Forks
- 1
- Merge medio
- 1 d 6 h
- PR fusionados (30 d)
- 5
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de nextlevelbuilder/dewee-webchat
-
ai-handle
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
-
ai-handle
Dificultad 3/5 1-2 días Aptitud para principiantes 38/100
-
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
-
ai-handle enhancement
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
-
ai-handle bug
Dificultad 4/5 3-5 días Aptitud para principiantes 53/100
Todos los issues de nextlevelbuilder/dewee-webchat
Issues similares
-
area:plugins area:security area:skills bug has repro
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
anthropics/claude-code#105911 ·
Los mantenedores suelen responder en 1 día
-
openspec-apply-change skill: when blocked, may select a ready artifact unrelated to missingArtifactsAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Fission-AI/OpenSpec#2165 ·
Los mantenedores suelen responder en 1 día
-
🐞 bug 🧐 unconfirmed
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
Tencent/tdesign-vue-next#7032 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
gnosis/gnosis_vpn#661 ·
Los mantenedores suelen responder en 1 día
-
content-freshness: staleOwnedContent doc comments still say 'complete receipt' (follow-up to #7912)Abiertotriage:bug-verified
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
Los mantenedores suelen responder en 1 día