feat(widget): safely render Markdown images for product photos and payment QR
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 38/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- html, markdown, typescript
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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
- Ngôn ngữ chính
- TypeScript
- Star
- 7
- Fork
- 1
- Merge trung bình
- 1 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 5
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của nextlevelbuilder/dewee-webchat
-
PHP backend: fixed file names in the shared temp dirCó thể đã có người làm @dannyward630 đã nhận hôm nay. Đang mởai-handle
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
-
ai-handle
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 38/100
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
-
ai-handle enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
-
ai-handle bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 53/100
Tất cả issue của nextlevelbuilder/dewee-webchat
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
area:desktop area:ui bug platform:macos
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
anthropics/claude-code#106183 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
reproduced
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
anomalyco/opencode#60558 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày