Skip to content

scanner_ranges: 厂商自报段接入 + eval 真值层排除 + 自报段标签呈现 - #216

Merged
steponeerror merged 13 commits into
masterfrom
feature/scanner-ranges
Oct 26, 2026
Merged

steponeerror merged 13 commits into
masterfrom
feature/scanner-ranges

Conversation

@steponeerror

Copy link
Copy Markdown
Owner

问题

各安全厂商/研究机构公开的研究扫描器自报 IP 段(互联网上广泛扫描),此前不在情报池中;而第三方观测类源(sw_scanners 等)会把这些段的成员标成恶意,eval 恶意真值语料因此被自报段污染(census 探针实测 400 采样 80.2% 被池标恶意)。用户令:公开扫描器不计代价全部拿到聚合为源。

方案(grill 2026-10-26 全裁,ADR 0011)

单源 scanner_ranges(cdn_edges 同构 _FEEDS 66+1):MISP warninglists 66 个非 nt 厂商自报列表(CC0)+ Xpanse 官方页直读 9 CIDR;Evidence(classification="scanner", verdict="malicious", native_categories 标签「研究扫描 · <厂商/机构>(自报段)」),r=0.90、stale_days=7、v4+v6 双族。verdict=malicious 是行为类型断言(词表 aggressive scanning),意图活在标签里,改判权留用户(与 sw_scanners 独立两票,corroborated +1 合法)。

eval 真值层装配侧剔除自报段成员(apply_scanner_filter 现成挂点,S12 语料版本随附,S17 趋势重置留痕)+ 冻结 benchmark 采样同步剔除(新增污染口)。产品查询路径零改;产品标恶意 + eval 剔除 = 刻意不对称,特性(ADR 0011)。

Closes #212, closes #213, closes #214, closes #215

裁决链:普查 docs/research/2026-10-26-scanner-ranges-census.md → grill 共识 → ADR docs/adr/0011-eval-exclusion-scanner-self-declared-ranges.md → GLOSSARY「自报段」「公开研究扫描」。

新源 backend/ipdb/_sources/scanner_ranges.py(cdn_edges 同构 Source 子类,
_discover_sources 自动注册):_FEEDS 66+1 = 66 个 MISP `*-scanning` 家族列表
(CC0/CIRCL,raw.githubusercontent 一跳镜像,URL 单模板)+ Xpanse 官方页直读
(cortex-docs scanning-activity,9 CIDR);download() 写合并中间件
scanner_ranges.csv (cidr,vendor),harvest() 映射 Evidence(scanner/malicious,
r=0.90,标签走 native_categories(spec 2026-10-26 补定,f3csystems.py:53 先例
→ detail dict → API 透传 → 前端 chip):「研究扫描 · <厂商/机构>(自报段)」,
67 条厂商映射全表;v4/v6 双族写入侧自动分派,裸 IP 收作 /32(实测 22 条);
dedup 同证据塌缩异厂并存;provenance_tier="B"(threat 类必声明);
authoritative_for=()(纯 corroboration,SM-F1);OpenFilters 镜像/-nt-/
GreyNoise 一概不接(spec 红线)。

测试 backend/tests/sources/test_scanner_ranges.py(7 例,offline):
_FEEDS 66+1 完整性(名字集=spec verbatim+红线锚)/MISP list.json 解析
(双族+裸 IP+垃圾弃)/Xpanse HTML 9 CIDR verbatim/证据契约整形状
(40.124.175.29 验收例)/dedup/health(rebuild=v4 键数契约,covered_v6_nets)/
registry 元数据落册。快照 test_metadata_derivation.py 随池合法更新:
OLD_CATEGORIES/OLD_RELIABILITY +scanner_ranges(threat/0.90),计数注释
50→51、43→44(rir_abuse 入册判例)。

门:backend/tests 全量 2251 passed/9 skipped;4 挂处置 = 2 快照(本 commit
修复,定向复验 core+sources+source_infra+eval+lookup 1791/0 全绿)+
test_health_round_real_run(基线同挂:agent 环境性,与源无关)+
test_memory_valve(负载 flake,单跑过,与源无关)。
环境注:本机 pytest 须 `python -S` + PYTHONPATH=<site-packages> 绕全局
sopagent editable-install .pth 的 tests 命名空间包污染(backend/tests 无
__init__.py 被常规包压过);CI 干净环境不受影响。

Closes nothing yet — SR-T2 eval 排除/SR-T3 渲染链/SR-T4 docs 后续票。
链路核实(全部通用透传,产品代码零改,用户裁定零新 UI 机制):
scanner_ranges harvest native_categories → _merge.py detail 组装
→ _types.py to_dict() classifications.details → _api_models.py
ClassificationOut.details list[dict] 透传(extra=allow)→ 前端
SourceDetailRow.tsx 通用 chip([全文])。

- backend tests/lookup/test_scanner_ranges_label.py:验收例
  40.124.175.29(Stretchoid)离线全链(真 lookup,仅换 _sources):
  malicious 判决照旧 + detail 四键精确钉(source/reliability=0.90/
  verdict/native_categories=["研究扫描 · Stretchoid(自报段)"])+
  corroborated=False + verdict_conflict 不点亮(无良性断言→无冲突面);
  LookupResultOut 响应模型面逐字段复钉(GET /api/lookup 与
  POST /api/query/stream 同构)。
- frontend SourceDetailRow.test.tsx:照 :82 先例钉 chip 全文字面量。

红证(tamper-red,不落 commit):摘 _merge.py native_categories
detail 键 → 后端 2 红;摘 SourceDetailRow.tsx chip map → 前端 3 红
(含本票);复原全绿。

门:后端定向 111 passed(tests/lookup + core merge/api 契约面 +
sources/test_scanner_ranges);前端 vitest 定向 11 passed。
新增 backend/ipdb/_eval/layer_builders.py::scanner_ranges_prefixes(csv_path)
(模块 docstring 注明寄住语义:truth ETL 本体仍在 truth_layer.py,本函数是
truth 侧唯一例外):逐行读 scanner_ranges 中间件 CSV 首列(cidr,vendor),
取逗号前 strip token;空行/纯空白跳过;CIDR/裸 IP/v6/坏 token 原样透传
——归一与坏值拦截归 apply_scanner_filter 侧 ip_network(「坏快照不许
静默缩水」,parse_rir_delegated 同款哲学)。原始 CSV 直读勿从 LMDB 反解
(无损管线,EXPLORE §4);ops 离线组装 scanlist = legacy 清单 + 本表喂
build_truth_layer(scanner_prefixes=...),换版经 scanlist_fingerprint
(S12)/趋势重置(S17)自动留痕(ADR 0011 装配侧剔除)。

缺失裁定(implementer 定,测试钉死):CSV 不在 → FileNotFoundError。
显式索取的排除清单缺席 = 装配错误,静默回空表会与 legacy 合表后无声
缩小排除面(语料悄然重染 80.2%);纯空表组合另有 gates_health
scanner_ok 的 DEGRADED 拒出版兜底(truth_layer S9)。benchmark 装配侧
(corpus.build_benchmark,D2)要「缺文件即无排除」语义,自行 is_file
前置判断。

测试 backend/tests/eval/test_eval_layer_builders.py +3(offline):
首列 token 读取(v4/v6/裸 IP/空行/坏 token 透传)/缺失 CSV raise/
空表如实回空。红先行:三例 ImportError(cannot import name
'scanner_ranges_prefixes')→ 实现 → 绿。

门:backend/tests/eval + backend/tests/core 定向 1215 passed/8 skipped
(命令见 SR-T2-REPORT.md;python -S + PYTHONPATH 绕 sopagent .pth 污染,
CI 不受影响)。
backend/ipdb/_eval/corpus.py::build_benchmark 两步(ADR 0011,签名不变,
__main__.py:666 调用点零改):①跳过 name=="scanner_ranges" 的源 —— 自报段
成员=厂商声明的段本身,非指控观测,入采样宇宙=自证污染;②采样/封顶后对
benchmark 每个分层过一遍自报段前缀:前缀取自该源 _path 指向的原始中间件
CSV(经 D1 scanner_ranges_prefixes 直读,勿从 LMDB 反解),段匹配复用
truth_layer.apply_scanner_filter —— 其他 scanner 源(sw_scanners 等)采出
的段内 IP 同剔(census 2026-10-26 实测 80.2% 扫描器 IP 已在自报段)。
宁少算不回补;v6 前缀值域与 v4 永不重叠,混排安全;benign/reserved 固定
小名单非采样面,不动。无 scanner_ranges 源或 CSV 缺失 → 行为与现状逐位
一致(排除器不启动,loader 的 raise 语义属 truth 装配侧,这里 is_file
前置走 noop 分支)。import 方向 corpus → truth_layer/layer_builders 单向
无环。

测试 backend/tests/eval/test_eval_corpus.py +3(offline,_FakeSource 样板):
剔除主例(三源混编,逐 IP 用 ipaddress 独立判段防 tautology,断言任一分层
零自报段成员+段外存活+scanner_ranges 源零贡献)/无源回归臂/CSV 缺失
noop 回归臂。红先行:主例 AssertionError: 40.124.175.29(段内成员存活)
→ 实现 → 绿;两回归臂按设计 green-on-arrival 钉现状。

门:backend/tests/eval + backend/tests/core 定向 1218 passed/8 skipped
(python -S + PYTHONPATH 绕 sopagent .pth 污染,CI 不受影响)。
零生产代码改动,测试钉住两条既有 seam(build_truth_layer 眾,monthly.py
零改;spec 设计定案 4 验收面):

1. test_eval_truth_layer.py +test_scanner_ranges_join_two_arm_exclusion_
   and_fingerprint:ops 两臂对照 —— arm A legacy scanlist(["10.0.0.0/8"]
   不覆盖目标),arm B legacy + D1 scanner_ranges_prefixes(fixture CSV
   v4+v6)。断言:40.124.175.29 ∈ arm A members、∉ arm B;
   removed_by_scanner_filter 差值精确(A=0,B=1);scanlist_fingerprint
   与语料 fingerprint 两臂皆变(S12 换版随附);两臂 load_asset 往返
   指纹一致(证据永不灭失)。

2. test_eval_monthly.py +test_md_reset_note_truth_two_arm_scanner_ranges_
   join:_header_meta/compose_monthly_md 既有 seam(:329-390 样板),两臂
   真产出的 truth 指纹作 prev/当轮,断言「换版=趋势重置(S12/S17)」
   注记行出现且点名 truth + 新旧指纹(assets/monthly 本身零改,
   RESET_NOTE_KINDS 含 "truth" 自动出注记)。

红先行:月报例红证据已在 D1 切片捕(ImportError: cannot import name
'scanner_ranges_prefixes',与 loader 三例同批 4 failed);两臂例依赖面
同源(D1 未落地即不可 import),green-on-arrival 钉零改面。

门:backend/tests/eval + backend/tests/core 定向 1220 passed/8 skipped
(python -S + PYTHONPATH 绕 sopagent .pth 污染,CI 不受影响)。
…161)+NEEDS 行27 已交付待合+CHANGELOG 双语条+test_eval_monthly 重复 import 清理(merger 注记)
@steponeerror

Copy link
Copy Markdown
Owner Author

双轴终审(批收口,基点 57163ad)

Standards 轴 PASS——零 P0/P1。九条哲学逐条对照合规且留痕(注释 why+出处/防回声/宁少算不回补/无损管线/门数字可复核,66+1 名单经实数复核);cdn_edges 同构逐字成立;测试真钉(corpus 例独立 ipaddress 复算防 tautology、label 整 dict 精确钉)。

Spec 轴 PASS——零 P0/P1,无 scope creep。66 名单 set+order 逐字等 spec 附录;Xpanse 9 CIDR 逐字;r=0.90/stale=7/tier B/authoritative_for=() 齐;corpus 剔除语义、S12/S17 两臂、双端标签契约全部核对通过;reviewer 独立复跑 source 9 绿+eval 65 绿+metadata 4 绿+前端 11 绿。

P2 处置(六条,零阻断)

P2 处置
GreyNoise 负断言缺失(CHANGELOG 宣称三条实有两条) ✅ 92de505 补齐断言
Xpanse 全页正则无零命中护栏(改版即静默缩水) ✅ 92de505 零命中 raise(与 loader 缺 CSV 同律)+tamper-red 测试;不设上限=页面新增 CIDR 属合法更新
GLOSSARY 锚精度(:129 实为类行,_FEEDS 在 :119) ✅ 已修
test 两臂 fixture 重复(truth_layer/monthly 各一份同构构造) 留档:双臂皆绿,cross-file import 有耦合风险,下批顺手
truth 生产装配调用面未换源(ops runbook 仍 legacy 手合资产) 已裁缓议:测量建言留 ops 轮人裁(票评/CHANGELOG 已明示)
单 feed 失败炸全量(与 cdn_edges 同构,spec 明文) 接受:同构语义,偶发失败=全源 stale 而非半新半旧

结论:批收口就绪,待 CI 绿后由用户裁决合并。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant