fix: round 10 critical fixes - WebSocket race, rate limiting, XSS protection, Caddyfile, and input validation

This commit is contained in:
2026-05-20 17:59:22 +08:00
parent a5b5713b29
commit 20cdcc748e
10 changed files with 336 additions and 25 deletions
@@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
"regexp"
"strings"
"time"
@@ -16,6 +17,9 @@ import (
"github.com/yourname/cyrene-ai/gateway/internal/store"
)
// usernameRegex 用户名格式校验:仅允许字母、数字、下划线,长度 3-32
var usernameRegex = regexp.MustCompile(`^[a-zA-Z0-9_]{3,32}$`)
// AuthHandler 认证处理器
type AuthHandler struct {
cfg *config.Config
@@ -49,6 +53,12 @@ func (h *AuthHandler) Register(c *gin.Context) {
return
}
// 用户名格式校验:仅允许字母、数字、下划线,长度 3-32
if !usernameRegex.MatchString(req.Username) {
c.JSON(http.StatusBadRequest, gin.H{"error": "用户名格式无效:仅允许字母、数字和下划线,长度 3-32 位"})
return
}
// MVP阶段:验证码简单校验 (开发环境接受 "000000")
if req.VerifyCode != "000000" {
c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误 (开发阶段请使用 000000)"})
@@ -118,6 +128,12 @@ func (h *AuthHandler) Login(c *gin.Context) {
return
}
// 用户名格式校验:仅允许字母、数字、下划线,长度 3-32
if !usernameRegex.MatchString(req.Username) {
c.JSON(http.StatusBadRequest, gin.H{"error": "用户名格式无效"})
return
}
var userID string
// 尝试从 users 表查询用户
@@ -1,6 +1,7 @@
package handler
import (
"html"
"log"
"net/http"
"os"
@@ -77,8 +78,8 @@ func (h *KnowledgeHandler) CreateKB(c *gin.Context) {
kb := &store.KnowledgeBase{
ID: store.GenerateUUID(),
UserID: userID,
Name: req.Name,
Description: req.Description,
Name: html.EscapeString(req.Name),
Description: html.EscapeString(req.Description),
}
if err := h.store.CreateKB(kb); err != nil {
@@ -175,7 +176,7 @@ func (h *KnowledgeHandler) UpdateKB(c *gin.Context) {
return
}
if err := h.store.UpdateKB(kbID, req.Name, req.Description); err != nil {
if err := h.store.UpdateKB(kbID, html.EscapeString(req.Name), html.EscapeString(req.Description)); err != nil {
log.Printf("[KnowledgeHandler] 更新知识库失败: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新知识库失败", "errorType": "db_error"})
return
@@ -315,8 +316,8 @@ func (h *KnowledgeHandler) AddDocument(c *gin.Context) {
ID: store.GenerateUUID(),
KBID: kbID,
UserID: userID,
Title: req.Title,
SourceType: req.SourceType,
Title: html.EscapeString(req.Title),
SourceType: html.EscapeString(req.SourceType),
SourceRef: sourceRef,
ContentType: contentType,
RawContent: content,
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"html"
"io"
"log"
"net/http"
@@ -144,11 +145,11 @@ func (h *MemoryHandler) Add(c *gin.Context) {
userID = req.UserID
}
// 转发到 Memory-Service
// 转发到 Memory-Service(对用户输入进行 HTML 转义防 XSS)
memReq := map[string]interface{}{
"user_id": userID,
"content": req.Content,
"category": req.Category,
"content": html.EscapeString(req.Content),
"category": html.EscapeString(req.Category),
"priority": req.Priority,
}
reqBody, _ := json.Marshal(memReq)
@@ -2,6 +2,7 @@ package handler
import (
"encoding/json"
"html"
"log"
"net/http"
"strconv"
@@ -113,8 +114,8 @@ func (h *ReminderHandler) Create(c *gin.Context) {
reminder := &store.Reminder{
ID: generateID(),
UserID: userID,
Title: req.Title,
Description: req.Description,
Title: html.EscapeString(req.Title),
Description: html.EscapeString(req.Description),
RemindAt: remindAt,
Status: "pending",
RepeatType: repeatType,