Escape user-supplied values in HTML email templates

Fixes #19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthew Knight 2026-02-17 16:02:01 -08:00
parent e3ef03ddcd
commit 244e530d4a
No known key found for this signature in database
1 changed files with 10 additions and 7 deletions

View File

@ -1,6 +1,9 @@
package email
import "fmt"
import (
"fmt"
"html"
)
func emailWrapper(content string) string {
return fmt.Sprintf(`<!DOCTYPE html>
@ -24,7 +27,7 @@ func renderVerificationEmail(name, verifyURL string) string {
</p>
<p>Or copy and paste this link into your browser:</p>
<p style="word-break: break-all; color: #2563eb;">%s</p>
<p>This link expires in 24 hours.</p>`, name, verifyURL, verifyURL))
<p>This link expires in 24 hours.</p>`, html.EscapeString(name), verifyURL, verifyURL))
}
func renderPasswordResetEmail(name, resetURL string) string {
@ -37,7 +40,7 @@ func renderPasswordResetEmail(name, resetURL string) string {
</p>
<p>Or copy and paste this link into your browser:</p>
<p style="word-break: break-all; color: #2563eb;">%s</p>
<p>This link expires in 1 hour. If you didn't request this, please ignore this email.</p>`, name, resetURL, resetURL))
<p>This link expires in 1 hour. If you didn't request this, please ignore this email.</p>`, html.EscapeString(name), resetURL, resetURL))
}
func renderTicketClosedEmail(name, ticketTitle, ticketURL string) string {
@ -48,7 +51,7 @@ func renderTicketClosedEmail(name, ticketTitle, ticketURL string) string {
<p style="margin: 30px 0;">
<a href="%s" style="background: #2563eb; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: 500;">View Ticket</a>
</p>
<p>If you believe the issue is not fully resolved, you can add a comment on the ticket page.</p>`, name, ticketTitle, ticketURL))
<p>If you believe the issue is not fully resolved, you can add a comment on the ticket page.</p>`, html.EscapeString(name), html.EscapeString(ticketTitle), ticketURL))
}
func renderTicketReplyEmail(name, ticketTitle, ticketURL string) string {
@ -58,7 +61,7 @@ func renderTicketReplyEmail(name, ticketTitle, ticketURL string) string {
<p>There is a new reply on your ticket <strong>"%s"</strong>.</p>
<p style="margin: 30px 0;">
<a href="%s" style="background: #2563eb; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: 500;">View Ticket</a>
</p>`, name, ticketTitle, ticketURL))
</p>`, html.EscapeString(name), html.EscapeString(ticketTitle), ticketURL))
}
func renderAccountApprovedEmail(name, loginURL string) string {
@ -68,7 +71,7 @@ func renderAccountApprovedEmail(name, loginURL string) string {
<p>Your account request has been approved. You can now log in and start creating tickets.</p>
<p style="margin: 30px 0;">
<a href="%s" style="background: #2563eb; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: 500;">Log In</a>
</p>`, name, loginURL))
</p>`, html.EscapeString(name), loginURL))
}
func renderWelcomeEmail(name, email, tempPassword, loginURL string) string {
@ -83,5 +86,5 @@ func renderWelcomeEmail(name, email, tempPassword, loginURL string) string {
<p style="margin: 30px 0;">
<a href="%s" style="background: #2563eb; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: 500;">Log In</a>
</p>
<p>Please change your password after logging in.</p>`, name, email, tempPassword, loginURL))
<p>Please change your password after logging in.</p>`, html.EscapeString(name), html.EscapeString(email), html.EscapeString(tempPassword), loginURL))
}