fix(安全): 修复依赖漏洞并强化安全扫描

主要改动:
- 固定 Go 1.25.5 与 CI 校验并更新扫描流程
- 升级 quic-go、x/crypto、req 等依赖并通过 govulncheck
- 强化 JWT 校验、TLS 配置与 xlsx 动态加载
- 新增审计豁免清单与校验脚本
This commit is contained in:
yangjianbo
2026-01-06 11:36:38 +08:00
parent d936eb6518
commit 3f0017d1f1
22 changed files with 1127 additions and 87 deletions

View File

@@ -20,12 +20,16 @@ var (
ErrEmailExists = infraerrors.Conflict("EMAIL_EXISTS", "email already exists")
ErrInvalidToken = infraerrors.Unauthorized("INVALID_TOKEN", "invalid token")
ErrTokenExpired = infraerrors.Unauthorized("TOKEN_EXPIRED", "token has expired")
ErrTokenTooLarge = infraerrors.BadRequest("TOKEN_TOO_LARGE", "token too large")
ErrTokenRevoked = infraerrors.Unauthorized("TOKEN_REVOKED", "token has been revoked")
ErrEmailVerifyRequired = infraerrors.BadRequest("EMAIL_VERIFY_REQUIRED", "email verification is required")
ErrRegDisabled = infraerrors.Forbidden("REGISTRATION_DISABLED", "registration is currently disabled")
ErrServiceUnavailable = infraerrors.ServiceUnavailable("SERVICE_UNAVAILABLE", "service temporarily unavailable")
)
// maxTokenLength 限制 token 大小,避免超长 header 触发解析时的异常内存分配。
const maxTokenLength = 8192
// JWTClaims JWT载荷数据
type JWTClaims struct {
UserID int64 `json:"user_id"`
@@ -309,7 +313,20 @@ func (s *AuthService) Login(ctx context.Context, email, password string) (string
// ValidateToken 验证JWT token并返回用户声明
func (s *AuthService) ValidateToken(tokenString string) (*JWTClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (any, error) {
// 先做长度校验,尽早拒绝异常超长 token降低 DoS 风险。
if len(tokenString) > maxTokenLength {
return nil, ErrTokenTooLarge
}
// 使用解析器并限制可接受的签名算法,防止算法混淆。
parser := jwt.NewParser(jwt.WithValidMethods([]string{
jwt.SigningMethodHS256.Name,
jwt.SigningMethodHS384.Name,
jwt.SigningMethodHS512.Name,
}))
// 保留默认 claims 校验exp/nbf避免放行过期或未生效的 token。
token, err := parser.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (any, error) {
// 验证签名方法
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])

View File

@@ -140,6 +140,8 @@ func (s *EmailService) SendEmailWithConfig(config *SMTPConfig, to, subject, body
func (s *EmailService) sendMailTLS(addr string, auth smtp.Auth, from, to string, msg []byte, host string) error {
tlsConfig := &tls.Config{
ServerName: host,
// 强制 TLS 1.2+,避免协议降级导致的弱加密风险。
MinVersion: tls.VersionTLS12,
}
conn, err := tls.Dial("tcp", addr, tlsConfig)
@@ -311,7 +313,11 @@ func (s *EmailService) TestSMTPConnectionWithConfig(config *SMTPConfig) error {
addr := fmt.Sprintf("%s:%d", config.Host, config.Port)
if config.UseTLS {
tlsConfig := &tls.Config{ServerName: config.Host}
tlsConfig := &tls.Config{
ServerName: config.Host,
// 与发送逻辑一致,显式要求 TLS 1.2+。
MinVersion: tls.VersionTLS12,
}
conn, err := tls.Dial("tcp", addr, tlsConfig)
if err != nil {
return fmt.Errorf("tls connection failed: %w", err)