[PR #1829] [MERGED] Fix HTML entity double-escaping in email notifications #5260

Closed
opened 2026-04-16 13:32:14 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/go-vikunja/vikunja/pull/1829
Author: @Copilot
Created: 11/15/2025
Status: Merged
Merged: 11/15/2025
Merged by: @kolaente

Base: mainHead: copilot/fix-issue-1664


📝 Commits (3)

  • 389aca8 Initial plan
  • ac0953f fix: remove double HTML escaping in email notifications
  • 088a8e4 test: add comprehensive XSS tests for email notifications

📊 Changes

2 files changed (+187 additions, -1 deletions)

View changed files

📝 pkg/notifications/mail_render.go (+1 -1)
📝 pkg/notifications/mail_test.go (+186 -0)

📄 Description

Email notifications were displaying HTML entity codes literally (") instead of rendering as characters ("), breaking readability for task titles containing quotes or other special characters.

Root Cause

convertLinesToHTML() was calling HTMLEscapeString() before goldmark's markdown conversion, causing double-escaping:

// Before: double-escaped
md := []byte(templatehtml.HTMLEscapeString(line.Text))  // "quote" → "quote"
goldmark.Convert(md, &buf)                               // → "quote"
// Result: " displayed literally in emails

// After: single proper escaping  
md := []byte(line.Text)                                  // "quote"
goldmark.Convert(md, &buf)                               // → "quote" → "quote"
// Result: " renders correctly in emails

Changes

  • pkg/notifications/mail_render.go: Removed premature HTMLEscapeString() call, letting goldmark handle escaping
  • pkg/notifications/mail_test.go: Added tests for special characters, pre-escaped entities, and comprehensive XSS attack vector tests

Security

Security is preserved through goldmark's HTML escaping and bluemonday's sanitization. Added 8 comprehensive XSS test cases covering common attack vectors:

  • Script tag injection (<script>)
  • Event handler injection (onerror, onclick)
  • JavaScript protocol URLs (javascript:)
  • Iframe injection
  • Data URIs with embedded scripts
  • Style tag injection with malicious CSS
  • Mixed malicious and legitimate markdown content

All XSS tests verify that malicious content is properly sanitized while legitimate content (markdown formatting, special characters) is preserved.

Original prompt

propose a fix for this: https://github.com/go-vikunja/vikunja/issues/1664


Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/go-vikunja/vikunja/pull/1829 **Author:** [@Copilot](https://github.com/apps/copilot-swe-agent) **Created:** 11/15/2025 **Status:** ✅ Merged **Merged:** 11/15/2025 **Merged by:** [@kolaente](https://github.com/kolaente) **Base:** `main` ← **Head:** `copilot/fix-issue-1664` --- ### 📝 Commits (3) - [`389aca8`](https://github.com/go-vikunja/vikunja/commit/389aca89a02f44d90627a6b3a01ce8299ddf8416) Initial plan - [`ac0953f`](https://github.com/go-vikunja/vikunja/commit/ac0953fe803f81e4e4b52863dbbef75c96e7b54f) fix: remove double HTML escaping in email notifications - [`088a8e4`](https://github.com/go-vikunja/vikunja/commit/088a8e448d2a0e73904064fa9c283dffd4a757ec) test: add comprehensive XSS tests for email notifications ### 📊 Changes **2 files changed** (+187 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `pkg/notifications/mail_render.go` (+1 -1) 📝 `pkg/notifications/mail_test.go` (+186 -0) </details> ### 📄 Description Email notifications were displaying HTML entity codes literally (`&#34;`) instead of rendering as characters (`"`), breaking readability for task titles containing quotes or other special characters. ## Root Cause `convertLinesToHTML()` was calling `HTMLEscapeString()` before goldmark's markdown conversion, causing double-escaping: ```go // Before: double-escaped md := []byte(templatehtml.HTMLEscapeString(line.Text)) // "quote" → &#34;quote&#34; goldmark.Convert(md, &buf) // → &amp;#34;quote&amp;#34; // Result: &#34; displayed literally in emails // After: single proper escaping md := []byte(line.Text) // "quote" goldmark.Convert(md, &buf) // → &quot;quote&quot; → &#34;quote&#34; // Result: " renders correctly in emails ``` ## Changes - **pkg/notifications/mail_render.go**: Removed premature `HTMLEscapeString()` call, letting goldmark handle escaping - **pkg/notifications/mail_test.go**: Added tests for special characters, pre-escaped entities, and comprehensive XSS attack vector tests ## Security Security is preserved through goldmark's HTML escaping and bluemonday's sanitization. Added 8 comprehensive XSS test cases covering common attack vectors: - Script tag injection (`<script>`) - Event handler injection (`onerror`, `onclick`) - JavaScript protocol URLs (`javascript:`) - Iframe injection - Data URIs with embedded scripts - Style tag injection with malicious CSS - Mixed malicious and legitimate markdown content All XSS tests verify that malicious content is properly sanitized while legitimate content (markdown formatting, special characters) is preserved. <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > propose a fix for this: https://github.com/go-vikunja/vikunja/issues/1664 </details> <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/go-vikunja/vikunja/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-16 13:32:14 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vikunja#5260