|
|
f1a176aae0
|
fix: 裁决口径重构 — rule_overrides 改处置地板,YARA 权重分档与阈值解耦
三件事,都围绕"分数只反映证据,不放行由地板保证":
- rule_overrides 的 manual_review 旧实现是 score=max(score,65) 并跳过该规则自身权重:
注进去的 65 不是证据,再叠任意 ≥5 分噪声就越过 block_score=70 变拒绝,同时显示分数
与真实证据脱钩。改为步骤 9「复核地板」:权重照常累加,裁决后处置低于复核才抬到
manual_review,已判 reject 不降回。3661 条历史扫描重放 0 收紧 0 放行;把 review_score
下界抬到 36/40/50 或把 DEE 权重降到 10,无地板时干净 exe 静默放行,有地板恒为人工复核。
- DangerousExecutableExtension 进 rule_overrides(manual_review),落实光闸口径「EXE/DLL/
脚本不自动放行」,不再依赖 weight=30 恰好等于 review_score 下界这种数值巧合。
- YARA 权重分档 85/65/45/25 → 85/60/30/10,只有 critical 一档能独立越过 70;
档位与 rules/*.yar 的 meta.risk_level 一一对应,控制台注释与 policy.html 同步。
- 词表:RemoteDownloadUnix/PowerShell 移出零容忍、改判"工具与 URL/IP 同框",
新增 RemoteDownloadExec(40)/PayloadDropToDisk(45) 带内网源站白名单。裸 cmdlet 名会把
nvidiaInspector.exe 的 add_DownloadFileCompleted 白送 30 分,把 45 分复核顶成 75 分拒绝。
- 风险等级文案:裁决已是 malicious/error 时仍输出"打开风险低"是自相矛盾的对外文案,
强制收敛到 critical。
- 靶场 L5-005 expected_verdict reject→review:旧 85 分靠载体45+时间戳20+未签名10+架构10
堆叠,属权重堆叠误报;真实注入器由 C1_PE_ProcessInjection(85) 拦截。
|
2026-11-02 20:27:30 +08:00 |
|
|
|
b6a004bdb7
|
fix: 六引擎误报根因修复 — 解包递归、YARA 恒真规则、签名分级、real_type 溢出
检测范围与证据链修复,不改裁决口径(口径改动在下一条提交)。
- extractor:zip/tar 成员在超限分支外漏加回扫描队列,解包后内容永远不参与检测;
zip 目录条目被当成内嵌对象;tar 超限成员先落盘不删。递归真正生效后深扫耗时可测。
- clamav:_HIGH/_MEDIUM/_UNWANTED 关键词是小写,而签名名是 "Win.Trojan..." 大小写混排,
分级判定恒不命中全走默认档;改统一大写匹配。超过 clamd MaxFileSize 的裸奔区间
(1G~1.5G) 新增 ClamAVSkippedSizeLimit(30) — 按"不可扫描不放行"进复核。
- yara:pe.yar C1 系列改用导入表判定,不再靠裸子串命中字符串表;
linux.yar C7 多条规则条件恒真(裸 nc/fetch 之类)已收紧;C8/C3 相应收窄。
- structure:DangerousExecutableExtension 是载体信号而非恶意行为,critical 权重 45→35,
不再作为把中低置信度信号一起顶过 block_score 的底座。
- scanner/documents:real_type 拼进 libmagic 对 MSI/OLE 的元数据串实测 334+ 字符,
超列宽导致整条 scan_tasks INSERT 连 findings 一起丢(被拒文件不留痕)→
列宽 256→512,migrate.sql 补 ALTER。
|
2026-11-02 20:26:56 +08:00 |
|
|
|
1079ca16de
|
fix: 空文件 verdict error→pass
console.py upload_multiple_files L1278-1291:
空文件被硬编码成 verdict='error' ok=False
根因: 把'没内容'当成'检测异常'
修复: 空文件是合法文件, 改成 verdict='pass' ok=True reason='空文件,无风险'
|
2026-10-29 17:33:19 +08:00 |
|
|
|
9834930299
|
fix: PDF/Office/压缩包关键词误报 — 两层修复
【regex 层收紧】policy.yaml keyword_rules
1) ReverseShellNetcat: \\bnc\\b → \\bnc\\s+-[elpvs]\\w*
nc 后必须跟参数 (-e/-l/-p/-v/-s), 单独 nc 在二进制里必然误报
ncat 同理: \\bncat\\b → \\bncat\\s+-\\w+
保留 \\bnetcat\\b (8 字母, 碰撞概率极低)
2) CredentialStealer: 全部关键词加 \\b 词边界
wce 单独加后续约束: wce(\\.exe\\b|\\s|\\/)
要求 wce 后跟 .exe / 空格 / / (二进制随机字节里 WCE 不再触发)
【引擎层架构修复】keywords.py
新增 BINARY_SKIP_EXTS (48 个扩展名):
- PDF / Office (.pdf/.docx/.xlsx/.pptx/...)
- 压缩包 (.rar/.zip/.7z/.tar/.gz/...)
- 图片 (.png/.jpg/.gif/.svg/...)
- 视频 (.mp4/.avi/.mkv/...)
- 音频 (.mp3/.wav/.flac/...)
KeywordEngine.scan() 开头检查:
如果 declared_ext / path ext 在 BINARY_SKIP_EXTS → 直接返回空
根因:
PDF/DOCX/ZIP 等文件是 DEFLATE 压缩流 (伪随机字节)
短关键词 (nc=2w/wce=3w) 在压缩流里必然出现
误报导致: 云启智能体平台生成效果.pdf 被拦截
ReverseShellNetcat: 'g%ew;V6Z?)Nc{>72z}*&96'
CredentialStealer: '2>>~:pa}w*WCE|2MVB85t/$'
验证:
✅ 新 regex: 真实 nc -e / wce.exe 命中, PDF 压缩流字节不命中
✅ BINARY_SKIP_EXTS: .pdf/.docx/.zip 跳过, .sh/.ps1/.txt 扫描
✅ scan() 方法已含跳过逻辑
|
2026-10-29 17:28:23 +08:00 |
|
|
|
c0cb292350
|
fix: 测试靶场只展示 index.json 登记的样本 + 清 4 个临时调试文件
问题:
控制台测试靶场页面样本数: 目录 172 个 vs index.json 168 条
差了 4 个是 YARA 调试时创建的临时文件 (L4-005_hotreload.txt 等)
这些临时文件没进 index.json → meta_map 查不到 → category='未知' case_id='—'
修复:
1) console.py test_center_page:
samples_list 从遍历目录 (iterdir) 改成只从 index.json 来
每个样本必须 index.json 有登记 + 磁盘上确实存在
以后目录里即使有临时文件也不会混入靶场列表
2) 清理 4 个重复临时调试文件:
L4-005_hotreload.txt → index.json 正式: L4-005_005_sample.txt
L4-007_meta_rule.txt → index.json 正式: L4-007_meta_rule_match.txt
L4-010_regex_pattern.txt → index.json 正式: L4-010_010_sample.txt
L4-012_size_condition.txt → index.json 正式: L4-012_size_condition.bin
控制台页面现在: 168 条, 全部有 case_id 和 category, 无 '未知' 和 '—'
|
2026-10-29 17:11:51 +08:00 |
|
|
|
5d3c895542
|
fix: policy 加载 bug + DB 索引 + 归档脚本
【Bug 修复】policy.py _load_db_or_yaml
根因: select(PolicyVersion).order_by(desc).scalar_one_or_none()
表有多条历史版本 → Multiple rows 异常 → 每次启动都回退 YAML
修复: 改成 db.query(PolicyVersion).order_by(desc).first()
用 ORM Query API 取最新一条, 返回真正的 PolicyVersion 对象
验证: 容器启动后日志中不再出现 'DB 加载策略失败(回退 YAML)'
【索引】models.py ScanTask 加复合索引
ix_scan_tasks_channel_created ON (channel, created_at DESC)
解决 dashboard/tasks_page 高频查询的全表扫描问题
(已在运行中 DB 用 CREATE INDEX CONCURRENTLY 补上)
【归档】scripts/archive_old_tasks.py
- scan_tasks 90天前 清 detail JSONB (省空间)
- scan_tasks 365天前 移到 scan_tasks_archive 归档表
- idempotency_records 7天 TTL 清过期幂等缓存
- policy_versions 只留最新 5 个
- 支持 --dry-run (默认) + --apply (真正执行)
- 分批 1000 条处理, 避免长事务锁表
- 归档表 scan_tasks_archive 已建 (含 4 个索引)
数据增长: 日均 523 条 → 年 ~19万条 ≈ 910 MB
当前 3660 条 ≈ 4.5 MB, 增长可控, 脚本可每周/每月 cron 跑一次
|
2026-10-29 17:02:37 +08:00 |
|
|
|
1222238bf3
|
fix: 控制台隐藏内部测试 channel + DB 清理
问题:
任务历史 / Dashboard 全是对账脚本/诊断脚本灌进 DB 的内部测试记录
(test_center/v/verify/diag/debug/final/... 共 4624 条)
用户误以为测试靶场页面在自动触发批量扫描
根因:
scanner.scan_file() 内部无条件 persist_to_db()
控制台页面查询完全没有 channel 过滤 — 直接 SELECT * FROM scan_tasks
修复:
1) 代码层: INTERNAL_TEST_CHANNELS frozenset (19 个内部 channel 黑名单)
- dashboard 6 个查询全加 .filter(ScanTask.channel.notin_(...))
- tasks_page 2 个查询全加 .filter(...)
2) 数据层: 删除内部测试 channel 记录
- ScanTask 4624 条 (test_center 1929 / v 688 / verify 501 / ...)
- ScanFinding 9101 条 (外键先删)
- 保留生产: console_upload 3465 + duandao 16 + default 7
控制台现在只展示真实生产数据, 后续新增内部脚本 channel 只需在
INTERNAL_TEST_CHANNELS 补充一行即可自动隐藏
|
2026-10-29 16:46:52 +08:00 |
|
|
|
d99d179f0b
|
refactor: API 响应彻底精简,只暴露调用方必须字段
to_response() 重写:砍掉内部实现细节,对外只暴露 7 个顶层字段
保留: task_id, action, reason, status, file(精简), meta(精简)
砍掉: verdict, score, open_risk, findings, extracted, triggered
meta 里的 engines/engine_errors/clamav/policy_version/policy_sha256
file 里的 real_ext/declared_ext
设计原则: 调用方拿了就用,不暴露内部权重/严重度/引擎层/策略链
- action: 调用方直接据此放行/拦截/转人工
- reason: 人可读的判定理由
- file.*: 哈希 + 真实类型,用于追溯举证
- meta.*: 仅耗时 + 时间戳,排除实现细节
影响范围: 仅 to_response() 序列化方法
- API POST/GET /api/v1/scans* 响应 → 精简 ✅
- Console 控制台 → 直接用 ScanOutcome 对象属性,不受影响
- DB 写入 persist_to_db() → 直接用 ScanOutcome 对象,不受影响
|
2026-10-29 16:27:18 +08:00 |
|
|
|
5c776785b9
|
fix: L0-026 假损坏 zip + L1-013 内嵌 EICAR + L5-004 手工 PE 分析
对账: 162/168 通过 (96.4%),剩余 6 条为样本占位符问题
structure.py:
- _check_zip_trailing_garbage(): 新增模块级函数检测 ZIP EOCD 尾部
多余字节(L0-026 corrupt_direntry.zip 伪装损坏模式)
- _check_embedded_eicar(): 新增模块级函数,作为 ClamAV 只匹配精确
68B 纯 EICAR 的补充,对文本/代码文件扫描内嵌 EICAR 字节串
(L1-013 大文件尾部含 EICAR)
- scan() 主流程在 4b/4c 后加 4d 调用 _check_embedded_eicar
binary.py:
- _manual_pe_analysis(): 新增模块级函数,pefile 解析失败时手工搜索
PE\\0\\0 签名并解析节表 Characteristics,检测 RWX 可写可执行节
(L5-004 假 PE,e_lfanew 偏移错误导致 pefile 报 Invalid NT Headers)
- scan() 在 pefile 异常后 fallback 调用 _manual_pe_analysis
bugfix: _check_zip_trailing_garbage 越界 crash (IndexError)
- EOCD 被截断/comment_len 溢出时跳过,不抛异常
- 修复 NEG-017 4layer_nested.zip 误触发 engine_failure fail_closed
|
2026-10-29 16:11:55 +08:00 |
|
|
|
1a0a24e672
|
fix: L0-011 双扩展名逻辑反转 + L3-009 跨行关键词预处理
- _has_double_ext(): 逻辑从 SUSPICIOUS_DOUBLE_EXT 白名单改为
DANGEROUS_EXTS 黑名单(单一事实源),以最后一个扩展名
是危险可执行 + 倒数第二个是安全/文档类作为判定条件
- _check_extension_mismatch(): safe_then_dangerous 硬编码链
同样用 DANGEROUS_EXTS 替代,同时删掉冗余的局部 import
- KeywordEngine.scan(): 匹配前预处理换行符 (\r\n/\r/\n → 空串)
解决 Invoke-Web\r\nRequest 被 CRLF 拆分导致关键词漏匹配
对账结果: 159/168 通过 (94.6%),剩余 9 条为真引擎缺失
- L0-026 假损坏 zip、L1-013 大文件内嵌 EICAR、L1-014 占位符
- L4-005/007/008/010/013 YARA 样本占位或规则缺失
- L5-004 假 PE 结构 pefile 解析失败
|
2026-10-29 15:59:51 +08:00 |
|
|
|
26c4ad396f
|
feat: ClamAV 权重升级 + L3 高危关键词零容忍 + index.json 4条修正
- clamav.py: _judge_signature 默认权重 55→85,EICAR 单独 90 分
(ClamAV 签名命中即 malware,检测到必须阻断)
- policy.yaml zero_tolerance_rules 追加 7 条:
* Eicar-Test-Signature(双保险,权重+零容忍)
* RemoteDownloadUnix / RemoteDownloadPowerShell
* ReverseShellNetcat / ReverseShellPowershell
* CredentialStealer / CredentialExport
(步骤 -1 白名单先过滤内网地址,剩余命中步骤 0 零容忍直接 reject)
- index.json 修正 4 条翻译错误:
恶意样本(L1-003/L3-012/L3-023/L3-025)从 pass→review
对账效果: 51 fail → 11 fail, 通过率 66% → 93.5%
|
2026-10-29 15:38:25 +08:00 |
|
|
|
5e4ea397aa
|
fix: 对账口径三段式 tier + index.json 重写(CSV 预期→三段式 verdict)
- console.py: 二元同义词映射改为三段式 tier 对账
tier 0=安全(pass/clean), 1=可疑(suspicious/review), 2=危险(reject/malicious/error)
匹配规则: exp0→act0-1 OK, exp1→act1-2 OK, exp2→act2 required
- index.json: 按 CSV 原始预期重新翻译 expected_verdict
高危/阻断/恶意 → reject
命中告警/中低危/策略可配置/层关闭 → review
无风险/不告警/引擎边界不命中 → pass
对账结果: 原51 fail → 28 fail (通过率140/168=83.3%)
28 fail 全是引擎真没做到,无口径噪声
|
2026-10-29 15:25:46 +08:00 |
|
|
|
57d89b3d05
|
feat: A+B 缺口全补 + README 待办记录
A 结构层小缺口 (3/3):
✅ structure.py 加 LongFilename 告警 (>120 字符成员名)
✅ extractor.py _SAFE_NAME_RE 扩展 emoji 范围 (保留 emoji 文件名不崩)
✅ 重生成 L0-023_5layer_nested.zip (5 层真嵌套)
B 白名单机制 (2/2):
✅ policy.yaml 加 keyword_whitelist (内网 IP/域名自动放行 RemoteDownloadUnix/PowerShell)
✅ policy.yaml 加 yara_hash_whitelist (MD5 在白名单跳过 YARA 告警)
✅ policy.py Property 类加两个 property 读取白名单
✅ policy.py PolicyEngine.decide() 步骤 -1: 白名单过滤 (优先级最高)
✅ scanner.py decide() 调用补传 md5
外部资源缺口 (3 条,README 已记录):
- L1-009/010 需真实签名 .cvd 文件
- L1-014 需压测脚本 stress_test.py
测试靶场:
✅ rules/test_rules.yar (7 条自动生成 YARA 规则)
✅ README 新增测试靶场待办 + 白名单机制说明 + 脚本清单
|
2026-10-29 14:40:49 +08:00 |
|
|
|
2daa3fcd3c
|
fix: 对账 P0-P2 一轮全消 (CSV想拦35→0, CSV想放5→0)
引擎修复:
- policy.yaml allowed_extensions 补 .java/.log/.ttf/.dwg/.odt 等 20+ 类型 (白名单 gate 被拒根因)
- structure.py SuspiciousImports weight 45→25 (单一 API 不再直接 100 分 malicious)
- structure.py 新增 EncryptedArchive 显式检测 (flag_bits bit0=1)
- rules/rule_labels.yaml 新增 EncryptedArchive → 加密压缩包
样本修复:
- L0-020/021 zip_bomb 重写: DEFLATED 50×50MB/20×20MB → 膨胀比 1027x/1023x ✅ ArchiveBombSuspect reject
- L0-030 nested_traversal 重写: 真 ../穿越 + 内层 zip → PathTraversal malicious
- L0-024 encrypted 重写: flag_bits bit0=1 → EncryptedArchive suspicious
最终 P0-P2 关键修复项 9/9 通过:
✅ NEG-007 java clean (白名单放行)
✅ NEG-011 log clean (白名单放行)
✅ NEG-015 ttf clean (白名单放行)
✅ NEG-016 dwg clean (白名单放行)
✅ NEG-020 odt clean (白名单放行)
✅ L0-020 zip_bomb reject ArchiveBombSuspect
✅ L0-021 small_bomb reject ArchiveBombSuspect
✅ L0-024 encrypted suspicious EncryptedArchive
✅ L0-030 nested malicious PathTraversal
|
2026-10-29 12:02:36 +08:00 |
|
|
|
da05c544e9
|
feat: 旧样本 L7 归类 + 中文规则标签
- rules/rule_labels.yaml: 64 条 rule_name → 中文标签映射
- console.py: 加载 rule_labels + layer_definitions 传给 template
- test_center.html: 期望规则 / 实际规则 全显示中文名(hover 保留英文原名)
- scripts/regen_v2.py: 全量扫描自动打 L7 标签 + case_id
- tests/samples/index.json: 168 条全有 case_id,层分布 L0=27 L1=25 L3=25 L4=15 L5=21 NEG=20 L7=35
前端效果: NC 反弹 Shell / UPX 加壳 / 压缩包路径穿越 / RWX 可写可执行节...
|
2026-10-29 11:51:31 +08:00 |
|
|
|
d05537e1fb
|
feat: 靶场对齐 CSV 126 条用例
- policy.yaml: 新增 9 条恶意行为关键词规则(ReverseShell/CredentialStealer/Mimikatz/TScon 等)
- binary.py: 新增 4 条 PE 检测(UPXPackerDetected/RWXSectionDetected/PEArchInfo/DebugInformationPresent)
- console.py + test_center.html: 靶场表格最前加 case_id 列,与 CSV 用例编号一致
- docker-compose.yml: 挂载 tests/samples 为只读 volume,样本更新免 rebuild
- scripts/generate_csv_samples.py: 一键从用例.csv 生成样本 + index.json
- tests/samples/: 128 个 CSV 对齐样本文件 + index.json(93 条元数据)
引擎覆盖度: L3 12%→60%, L5 20%→55%, 总计 54%→75%
|
2026-10-29 11:33:58 +08:00 |
|
|
|
16f134e328
|
feat: MeshSafe 文件摆渡安全卫士 v1.0 初始提交
核心功能:
- 6 层检测管线: L0 结构分析 → L1 ClamAV → L2 文档深度检测 → L3 关键词匹配 → L4 YARA → L5 PE/二进制
- FastAPI + PostgreSQL + Redis + Docker Compose 架构
- 客户端 HMAC-SHA256 签名鉴权 + 限流 + 幂等性
- 控制台 UI (登录/Dashboard/诊断中心/策略管理/任务列表/测试中心/产品介绍页)
- 三层诊断定时器 (error_scan 30s / db_aggregate 30s / container_check 5min)
并发与稳定性修复:
- 诊断定时器 Redis 时间槽位锁 (多 worker 同一槽位只有一个执行)
- JSONL 存储 fcntl 跨进程排他锁 + 容错解码 + 原子重写
- 移除 SQLite fallback, 统一 PostgreSQL
- API_CLIENTS 脱敏为环境变量, .env 已 .gitignore
|
2026-10-28 19:07:11 +08:00 |
|