实现分层实体漏洞知识库与实体级完整度监控
这个提交包含在:
@@ -5,7 +5,22 @@ from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterable, List
|
||||
|
||||
from intel.config import FRAMEWORK_ROOT, GENERATED_DIR, REGISTRY_ROOT, ROOT, SECURE_CODE_ROOT, SYSTEMS_DIR, TRIAGE_DIR
|
||||
from intel.config import (
|
||||
ENTITY_BACKLOG_PATH,
|
||||
ENTITY_BACKLOG_REPORT_MD_PATH,
|
||||
ENTITY_CATALOG_REPORT_MD_PATH,
|
||||
ENTITY_COMPLETENESS_PATH,
|
||||
ENTITY_QUEUES_PATH,
|
||||
ENTITIES_DIR,
|
||||
FRAMEWORK_ROOT,
|
||||
GENERATED_DIR,
|
||||
REGISTRY_ROOT,
|
||||
ROOT,
|
||||
SECURE_CODE_ROOT,
|
||||
SYSTEMS_DIR,
|
||||
TRIAGE_DIR,
|
||||
)
|
||||
from intel.entities import build_entity_views
|
||||
from intel.models import AdvisoryRecord
|
||||
from intel.utils import ensure_dir, isoformat, now_utc, write_json, write_text
|
||||
from lab.render import render_dashboard as render_lab_dashboard
|
||||
@@ -218,6 +233,25 @@ def _sync_selected_json_dir(path: Path, payloads: Dict[str, Any], selected_syste
|
||||
write_json(path / filename, payload)
|
||||
|
||||
|
||||
def _sync_selected_entity_json_dir(path: Path, payloads: Dict[str, Any], selected_system_ids: set[str]) -> None:
|
||||
ensure_dir(path)
|
||||
desired = set(payloads.keys())
|
||||
for file_path in path.glob("*.json"):
|
||||
payload = None
|
||||
try:
|
||||
payload = file_path.read_text(encoding="utf-8")
|
||||
except OSError:
|
||||
continue
|
||||
if not payload:
|
||||
continue
|
||||
if not any(file_path.stem == system_id or file_path.stem.startswith(f"{system_id}--") for system_id in selected_system_ids):
|
||||
continue
|
||||
if file_path.name not in desired:
|
||||
file_path.unlink()
|
||||
for filename, payload in payloads.items():
|
||||
write_json(path / filename, payload)
|
||||
|
||||
|
||||
def render_system_scaffolding(
|
||||
source_map: Dict[str, Any],
|
||||
advisories: List[AdvisoryRecord],
|
||||
@@ -386,6 +420,9 @@ def render_case_pages(advisories: List[AdvisoryRecord], selected_system_ids: set
|
||||
lines.append("fixed_versions:")
|
||||
for version in (item.fixed_versions or [])[:20]:
|
||||
lines.append(f' - "{version}"')
|
||||
lines.append("entity_refs:")
|
||||
for ref in item.entity_refs or []:
|
||||
lines.append(f' - "{ref.get("entity_id", "")}:{ref.get("entity_type", "")}:{ref.get("relation", "")}"')
|
||||
lines.append("secure_code_topics:")
|
||||
for topic in item.secure_code_topics or []:
|
||||
lines.append(f' - "{topic}"')
|
||||
@@ -415,6 +452,26 @@ def render_case_pages(advisories: List[AdvisoryRecord], selected_system_ids: set
|
||||
f"- 影响版本: `{', '.join((item.affected_versions or [])[:10]) or 'unknown'}`",
|
||||
f"- 修复版本: `{', '.join((item.fixed_versions or [])[:10]) or 'unknown'}`",
|
||||
"",
|
||||
"## 对象与版本映射",
|
||||
"",
|
||||
f"- Advisory Scope: `{item.advisory_scope or 'core'}`",
|
||||
f"- 影响对象: `{', '.join(component.get('name', '-') for component in (item.affected_components or [])) or 'unknown'}`",
|
||||
f"- Entity Refs: `{', '.join(ref.get('entity_id', '-') for ref in (item.entity_refs or [])) or 'unknown'}`",
|
||||
f"- 版本置信度: `{item.version_confidence or 'unknown'}`",
|
||||
f"- 版本缺口: `{item.version_gap_reason or '-'}`",
|
||||
f"- 版本证据源: `{', '.join((item.version_evidence_sources or [])[:5]) or 'unknown'}`",
|
||||
"",
|
||||
"## 受控验证流程",
|
||||
"",
|
||||
f"- Workflow ID: `{item.workflow.get('workflow_id') or '-'}`",
|
||||
f"- 漏洞家族: `{item.workflow.get('vuln_family') or '-'}`",
|
||||
f"- 入口面: `{item.workflow.get('entry_surface') or '-'}`",
|
||||
f"- 需要角色: `{item.workflow.get('required_role') or '-'}`",
|
||||
f"- 触发向量: {item.workflow.get('trigger_vector') or '-'}",
|
||||
f"- 请求/页面入口: `{', '.join(item.workflow.get('request_or_ui_path', [])[:5]) or '-'}`",
|
||||
f"- 输入形态: {item.workflow.get('input_shape') or '-'}",
|
||||
f"- 预期不安全行为: {item.workflow.get('expected_unsafe_behavior') or '-'}",
|
||||
"",
|
||||
"## 其他来源",
|
||||
"",
|
||||
]
|
||||
@@ -427,6 +484,28 @@ def render_case_pages(advisories: List[AdvisoryRecord], selected_system_ids: set
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
"## 证据点与补丁验证",
|
||||
"",
|
||||
]
|
||||
)
|
||||
for section, values in [
|
||||
("服务端证据点", item.workflow.get("server_evidence_points", [])),
|
||||
("浏览器证据点", item.workflow.get("browser_evidence_points", [])),
|
||||
("数据库/文件系统证据点", item.workflow.get("db_or_fs_evidence_points", [])),
|
||||
("检测信号", item.workflow.get("detection_signals", [])),
|
||||
("补丁验证步骤", item.workflow.get("patch_validation_steps", [])),
|
||||
("实验安全备注", item.workflow.get("lab_safety_notes", [])),
|
||||
]:
|
||||
lines.append(f"### {section}")
|
||||
lines.append("")
|
||||
if values:
|
||||
for value in values:
|
||||
lines.append(f"- {value}")
|
||||
else:
|
||||
lines.append("- 未定义")
|
||||
lines.append("")
|
||||
lines.extend(
|
||||
[
|
||||
"## 实验层",
|
||||
"",
|
||||
"- 仅用于自有资产、测试环境或已明确授权目标。",
|
||||
@@ -454,6 +533,7 @@ def render_registry(
|
||||
selected_system_ids: set[str] | None = None,
|
||||
) -> None:
|
||||
run_map = latest_runs_by_advisory()
|
||||
entity_views = build_entity_views(source_map, advisories)
|
||||
grouped: Dict[str, List[AdvisoryRecord]] = defaultdict(list)
|
||||
advisory_payloads: Dict[str, Dict[str, Any]] = {}
|
||||
for advisory in advisories:
|
||||
@@ -497,10 +577,17 @@ def render_registry(
|
||||
_sync_selected_json_dir(REGISTRY_ROOT / "advisories", advisory_payloads, selected_system_ids)
|
||||
_sync_selected_json_dir(TRIAGE_DIR, triage_payloads, selected_system_ids)
|
||||
_sync_selected_json_dir(REGISTRY_ROOT / "systems", system_payloads, selected_system_ids, systems_dir=True)
|
||||
selected_entity_payloads = {
|
||||
filename: payload
|
||||
for filename, payload in entity_views["entity_payloads"].items()
|
||||
if payload.get("root_system_id") in selected_system_ids
|
||||
}
|
||||
_sync_selected_entity_json_dir(ENTITIES_DIR, selected_entity_payloads, selected_system_ids)
|
||||
return
|
||||
_sync_json_dir(REGISTRY_ROOT / "advisories", advisory_payloads)
|
||||
_sync_json_dir(TRIAGE_DIR, triage_payloads)
|
||||
_sync_json_dir(REGISTRY_ROOT / "systems", system_payloads)
|
||||
_sync_json_dir(ENTITIES_DIR, entity_views["entity_payloads"])
|
||||
|
||||
|
||||
def render_generated(
|
||||
@@ -513,6 +600,7 @@ def render_generated(
|
||||
ensure_dir(GENERATED_DIR)
|
||||
systems = {item["system_id"]: item for item in source_map["systems"]}
|
||||
run_map = latest_runs_by_advisory()
|
||||
entity_views = build_entity_views(source_map, advisories)
|
||||
change_summary = change_summary or {}
|
||||
triage_by_system: Dict[str, List[Dict[str, Any]]] = defaultdict(list)
|
||||
for item in triage:
|
||||
@@ -549,6 +637,8 @@ def render_generated(
|
||||
f"- 渲染时间: `{isoformat(now_utc())}`",
|
||||
f"- 系统数量: `{len(source_map['systems'])}`",
|
||||
f"- Advisory 数量: `{len(advisories)}`",
|
||||
f"- 已编目实体数量: `{entity_views['completeness']['cataloged_entity_total']}`",
|
||||
f"- 待编目 backlog 数量: `{entity_views['completeness']['candidate_entity_total']}`",
|
||||
f"- 重点 Markdown 数量: `{markdown_total}`",
|
||||
f"- Run Bundle 数量: `{len(run_map)}`",
|
||||
f"- 新增记录: `{change_summary.get('new_count', 0)}`",
|
||||
@@ -568,6 +658,8 @@ def render_generated(
|
||||
"generated_at": isoformat(now_utc()),
|
||||
"system_count": len(source_map["systems"]),
|
||||
"advisory_count": len(advisories),
|
||||
"cataloged_entity_total": entity_views["completeness"]["cataloged_entity_total"],
|
||||
"candidate_entity_total": entity_views["completeness"]["candidate_entity_total"],
|
||||
"markdown_count": markdown_total,
|
||||
"new_count": change_summary.get("new_count", 0),
|
||||
"updated_count": change_summary.get("updated_count", 0),
|
||||
@@ -577,6 +669,11 @@ def render_generated(
|
||||
"failures": failures,
|
||||
},
|
||||
)
|
||||
write_json(ENTITY_COMPLETENESS_PATH, entity_views["completeness"])
|
||||
write_json(ENTITY_BACKLOG_PATH, entity_views["candidate_backlog"])
|
||||
write_json(ENTITY_QUEUES_PATH, entity_views["queues"])
|
||||
write_text(ENTITY_CATALOG_REPORT_MD_PATH, entity_views["catalog_report_markdown"])
|
||||
write_text(ENTITY_BACKLOG_REPORT_MD_PATH, entity_views["backlog_report_markdown"])
|
||||
render_lab_dashboard(
|
||||
advisory_records=[item.to_dict() for item in advisories],
|
||||
source_map_data=source_map,
|
||||
|
||||
在新工单中引用
屏蔽一个用户