mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-02 14:56:38 +08:00
fix(security): harden PoW XSS, email header injection and UptimeKuma log redaction
This commit is contained in:
+15
-6
@@ -12,6 +12,7 @@ import (
|
||||
"net"
|
||||
"net/smtp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -29,6 +30,14 @@ type Config struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
// sanitizeHeaderValue removes CR/LF bytes so untrusted values cannot inject
|
||||
// additional email headers (email header injection).
|
||||
func sanitizeHeaderValue(v string) string {
|
||||
v = strings.ReplaceAll(v, "\r", "")
|
||||
v = strings.ReplaceAll(v, "\n", "")
|
||||
return v
|
||||
}
|
||||
|
||||
// SendMail sends an HTML email using the provided config and message details
|
||||
func SendMail(ctx context.Context, cfg Config, to string, subject, body string) error {
|
||||
return SendMailHTML(ctx, cfg, to, subject, body)
|
||||
@@ -40,9 +49,9 @@ func SendMailHTML(ctx context.Context, cfg Config, to string, subject, body stri
|
||||
|
||||
// Header & MIME settings for HTML email
|
||||
header := make(map[string]string)
|
||||
header["From"] = cfg.Username
|
||||
header["To"] = to
|
||||
header["Subject"] = subject
|
||||
header["From"] = sanitizeHeaderValue(cfg.Username)
|
||||
header["To"] = sanitizeHeaderValue(to)
|
||||
header["Subject"] = sanitizeHeaderValue(subject)
|
||||
header["MIME-Version"] = "1.0"
|
||||
header["Content-Type"] = "text/html; charset=UTF-8"
|
||||
|
||||
@@ -212,9 +221,9 @@ func SendMailWithLog(ctx context.Context, cfg Config, to string, subject, body s
|
||||
|
||||
// Header & MIME settings for HTML email
|
||||
header := make(map[string]string)
|
||||
header["From"] = cfg.Username
|
||||
header["To"] = to
|
||||
header["Subject"] = subject
|
||||
header["From"] = sanitizeHeaderValue(cfg.Username)
|
||||
header["To"] = sanitizeHeaderValue(to)
|
||||
header["Subject"] = sanitizeHeaderValue(subject)
|
||||
header["MIME-Version"] = "1.0"
|
||||
header["Content-Type"] = "text/html; charset=UTF-8"
|
||||
|
||||
|
||||
@@ -90,3 +90,23 @@ func TestSendMailMock(t *testing.T) {
|
||||
t.Errorf("failed to send mail: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSanitizeHeaderValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{"plain", "System Notification", "System Notification"},
|
||||
{"crlf stripped", "alert\r\nBcc: attacker@example.com", "alertBcc: attacker@example.com"},
|
||||
{"cr stripped", "a\rb", "ab"},
|
||||
{"lf stripped", "a\nb", "ab"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := sanitizeHeaderValue(tt.input); got != tt.want {
|
||||
t.Errorf("sanitizeHeaderValue(%q) = %q, want %q", tt.input, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user