fix: 修复合并后审查发现的 6 个中/高问题
#102 高:证据正文下载在全局 advisory lock 事务内 io.Copy 给 HTTP 客户端, verifyFile 又要整读一遍算 SHA-256 —— 一次大文件下载或慢客户端就会挂住 全进程的证据写入。改为事务内只解析绑定元数据(Store.Binding),出锁后再校验 与串流;blob 内容寻址且 GC 有 24h 宽限,已打开的 fd 也不受 unlink 影响。 #102 高:traffic_evidence_snapshots 的 url/req_head/resp_head 直接来自目标 原始报文,未清洗就写 PG TEXT。目标返回非 UTF-8 头(GBK filename)或 NUL 会让 RecordFindingTx 整个事务回滚,已确认的漏洞完全不落库。新增 TrafficEvidenceSnapshot.Normalize(),在算 ID 之前套用仓库既有的 utf8Clean, 保证哈希与入库字节一致。 #102 中:自动绑定默认关闭,reporter 便不会传 evidence_version, SetFindingReportVersionByNodeID 按 legacy 语义写 -1,报告永久显示「待更新」 且 UI 无处清除;老库还因 reporter_agent_seed_v1 守卫拿不到新触发文案。 触发消息改为无条件先读 get_finding_traffic(只读工具,不依赖捕获开关)并回传 版本,并加一次性迁移刷新老库中未被用户改动的默认文案。 #102 中:开关关闭时 report_finding 只要收到 traffic_refs/evidence_hint_id 就在写入前报错,模型幻觉出多余字段即丢掉一个真实漏洞。改为忽略这两个参数 照常登记,由既有的 evidence_status=not_bound 说明未绑定。 #101 中:删掉 RuleID!=0 判断后,每次模型放行都写一行带完整审计快照的 intercept_pending(单行最坏 24×8KiB 上下文 + 32KiB 输入)。开启兜底裁判的 渗透任务会灌入数百 MB,并经 task_archives 的 SELECT * 进入归档。放行行改为 只留决策元数据与执行结果,丢掉重放快照;ask/deny 路径不变。 #103 中:FindingRetestForConversation 出错时在收尾 defer 注册前就 return, 复测行永远停在 pending —— 漏洞列表常驻「复测中」,后续发起复测被去重拦下, 只有重启才能清。新增 FailPendingRetestForConversation 按会话 ID 收尾。
This commit is contained in:
1 parent
e8efce605c
commit
72a52e9202
10 files changed
+197
-55
No files matched your search
@@ -109,7 +109,24 @@ type PreparedTrafficEvidence struct {
|
||||
Snapshot TrafficEvidenceSnapshot
|
||||
}
|
||||
|
||||
// Normalize makes the snapshot's text columns safe for PostgreSQL. URL and the
|
||||
// head blocks come straight off the wire, so a target answering with a non-UTF-8
|
||||
// header (a GBK `Content-Disposition: filename=…`, a NUL byte) would otherwise
|
||||
// abort the INSERT and roll back the whole finding — losing a confirmed finding
|
||||
// over a malformed response header. Applied before hashing so the ID always
|
||||
// matches the bytes that actually land in the table.
|
||||
func (s TrafficEvidenceSnapshot) Normalize() TrafficEvidenceSnapshot {
|
||||
s.SourceTrafficID = utf8Clean(s.SourceTrafficID)
|
||||
s.URL = utf8Clean(s.URL)
|
||||
s.Method = utf8Clean(s.Method)
|
||||
s.ContentType = utf8Clean(s.ContentType)
|
||||
s.ReqHead = utf8Clean(s.ReqHead)
|
||||
s.RespHead = utf8Clean(s.RespHead)
|
||||
return s
|
||||
}
|
||||
|
||||
func TrafficSnapshotID(snapshot TrafficEvidenceSnapshot) string {
|
||||
snapshot = snapshot.Normalize()
|
||||
snapshot.ID = ""
|
||||
snapshot.CreatedAt = time.Time{}
|
||||
raw, _ := json.Marshal(snapshot)
|
||||
@@ -169,6 +186,10 @@ func InsertEvidenceSnapshotTx(tx *sql.Tx, s TrafficEvidenceSnapshot) error {
|
||||
if s.ID != TrafficSnapshotID(s) {
|
||||
return errors.New("证据快照元数据哈希不匹配")
|
||||
}
|
||||
// The ID was computed over the normalized form; store those same bytes.
|
||||
id := s.ID
|
||||
s = s.Normalize()
|
||||
s.ID = id
|
||||
if s.CreatedAt.IsZero() {
|
||||
s.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user