fix(security,data): P0 — 命令注入/停止毁数据/采集路径绕过/DB 清库/前端竞态

后端(实机 10.10.10.161 验证 host-binary 全链路 + 注入双路径 400):
- Loki 版本号严格 ^\d+.\d+.\d+$ 校验并接入 Update 路径:version 拼进 SSH shell 命令,
  旧校验放行 3.0.0'; id; echo ' 等注入载荷(root RCE)
- Stop/Restart 清理清单移除 PVC:停止部署曾连带删除 loki-data PVC,filesystem 存储日志被永久清空(测试锁死红线)
- 采集敏感路径防护覆盖默认 LogPath 分支与 collector Create(/etc/shadow 不再可绕过入库)
- 数据文件损坏时原文件改名 .corrupt-* 留档再空库启动,不再被静默覆盖(loadFromDisk 抽出可测)

前端:
- 审计页用户名过滤 300ms 防抖 + AbortController/版本号(逐键竞态数据错乱)
- 向导自动部署改用创建返回实例(或 id 最大且 pending),不再盲取 list[0] 对错误实例发起真实部署
- 路由级 ErrorBoundary:单页崩溃/chunk 404 只影响当前页
This commit is contained in:
opsx committed 2026-10-29 13:02:11 +08:00
1 parent 5e59347c40
commit 2975452c21
17 files changed
+271 -68

No files matched your search

+10 -3
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net"
"regexp"
"strconv"
"strings"
"sync"
@@ -255,6 +256,9 @@ func (s *DeploymentService) Update(id uint, updates map[string]interface{}) erro
db.Deployments[i].Description = v
}
if v, ok := updates["version"].(string); ok && v != "" {
if err := ValidateLokiVersion(v); err != nil {
return err
}
db.Deployments[i].Version = v
}
if v, ok := updates["namespace"].(string); ok && v != "" {
@@ -601,17 +605,20 @@ func (s *DeploymentService) getEndpoint(d *models.LokiDeployment) string {
// ==================== 版本兼容性检查 ====================
// ValidateLokiVersion 检查 Loki 版本是否在支持列表中且满足最低版本要求
// lokiVersionPattern 版本号会被拼进主机上的 shell 命令(下载 URL 等),
// 只放行纯数字三段式,从根上杜绝引号/命令替换等注入
var lokiVersionPattern = regexp.MustCompile(`^\d+\.\d+\.\d+$`)
func ValidateLokiVersion(version string) error {
if version == "" {
return nil // 使用默认值,不报错
}
// 基本格式验证
parts := strings.Split(version, ".")
if len(parts) < 2 {
if !lokiVersionPattern.MatchString(version) {
return fmt.Errorf("版本号格式无效: %s,期望格式如 3.0.0", version)
}
parts := strings.Split(version, ".")
major, err := strconv.Atoi(parts[0])
if err != nil {
return fmt.Errorf("无法解析主版本号: %s", version)