Files
MeshSate/app/i18n_labels.py
zhaolei 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

282 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""MeshSafe 统一中文标签体系。
所有控制台页面(概览 / 任务历史 / 测试靶场)共用同一套中文映射,
保证同一个后端字段在任何页面显示的名称、颜色、说明完全一致。
设计目标
--------
1. **术语统一** —— verdict / action / severity / engine / mode 全部中文化,
英文原值保留在 title 属性里供运维排查时对照。
2. **风险分级体系** —— 把「放行 / 可疑 / 恶意 / 策略拒绝 / 异常」归入
4 个风险等级(安全 / 注意 / 高危 / 故障),与策略引擎的裁决语义对齐。
3. **单一事实源** —— 新增页面或新增字段时只需在这里登记,
不用再到每个模板里写一遍 if-else。
"""
from __future__ import annotations
from typing import Any, Dict, List, Optional, Tuple
# =============================================================================
# 风险等级体系(全局统一)
# =============================================================================
#: 风险等级 → (中文名, 徽章 CSS 类, 语义说明)
RISK_LEVELS: Dict[str, Tuple[str, str, str]] = {
"safe": ("安全", "ok", "未检出任何风险信号,正常放行"),
"notice": ("注意", "warn", "存在可疑信号,建议人工确认后放行"),
"high": ("高危", "bad", "确认存在恶意特征,必须阻断"),
"fault": ("故障", "err", "检测过程异常,按安全优先策略阻断"),
"idle": ("处理中", "muted", "检测尚未完成"),
}
#: 风险等级排序(从高到低),用于排序统计
RISK_ORDER: List[str] = ["high", "notice", "fault", "safe", "idle"]
# =============================================================================
# 裁决结论(verdict)
# =============================================================================
#: verdict → (中文名, 风险等级)
VERDICT_LABELS: Dict[str, Tuple[str, str]] = {
"clean": ("放行", "safe"),
"pass": ("放行", "safe"),
"known": ("放行", "safe"),
"suspicious": ("可疑", "notice"),
"review": ("可疑", "notice"),
"malicious": ("恶意", "high"),
"reject": ("策略拒绝", "fault"),
"error": ("检测异常", "fault"),
"pending": ("处理中", "idle"),
}
# =============================================================================
# 处置动作(action)
# =============================================================================
#: action → (中文名, 风险等级)
ACTION_LABELS: Dict[str, Tuple[str, str]] = {
"pass": ("放行", "safe"),
"pass_with_flag": ("带标记放行", "notice"),
"manual_review": ("人工复核", "notice"),
"reject": ("拦截", "high"),
"reject_and_notify": ("拦截并告警", "high"),
"error": ("异常阻断", "fault"),
"pending": ("处理中", "idle"),
}
# =============================================================================
# 严重度(severity)
# =============================================================================
#: severity → (中文名, 徽章 CSS 类)
SEVERITY_LABELS: Dict[str, Tuple[str, str]] = {
"critical": ("严重", "bad"),
"high": ("高危", "bad"),
"medium": ("中危", "warn"),
"low": ("低危", "notice"),
"info": ("提示", "muted"),
}
# =============================================================================
# 检测引擎(engine)
# =============================================================================
ENGINE_LABELS: Dict[str, str] = {
"structure": "文件结构分析",
"clamav": "ClamAV 病毒库",
"document": "文档深度检测",
"keywords": "关键词匹配",
"yara": "YARA 规则匹配",
"binary": "PE/二进制分析",
"extractor": "归档解压",
}
# =============================================================================
# 扫描模式(mode)
# =============================================================================
MODE_LABELS: Dict[str, str] = {
"sync": "同步",
"async": "异步",
}
# =============================================================================
# 样本分类(测试靶场 category)
# =============================================================================
CATEGORY_LABELS: Dict[str, str] = {
"web_shell": "Webshell",
"office_macro": "Office 宏",
"windows_pe": "Windows 可执行",
"linux_malware": "Linux 恶意脚本",
"zero_tolerance": "零容忍载体",
"encrypted": "加密文档",
"negative": "阴性对照",
"unknown": "未分类",
}
# =============================================================================
# 渠道(channel)—— 摆渡来源
# =============================================================================
CHANNEL_LABELS: Dict[str, str] = {
"default": "默认通道",
"duandao": "摆渡通道",
"console_upload": "控制台上传",
"test_center": "测试靶场",
}
# =============================================================================
# 对外查询接口
# =============================================================================
def verdict_label(verdict: Any) -> str:
"""verdict → 中文名(未知值原样返回)。"""
key = str(verdict or "").strip().lower()
return VERDICT_LABELS.get(key, (str(verdict or "-"), "idle"))[0]
def verdict_risk(verdict: Any) -> str:
"""verdict → 风险等级 key。"""
key = str(verdict or "").strip().lower()
return VERDICT_LABELS.get(key, ("-", "idle"))[1]
def verdict_badge(verdict: Any) -> str:
"""verdict → 徽章 CSS 类。"""
key = str(verdict or "").strip().lower()
return RISK_LEVELS.get(verdict_risk(key), ("-", "muted"))[1]
def action_label(action: Any) -> str:
"""action → 中文名。"""
key = str(action or "").strip().lower()
return ACTION_LABELS.get(key, (str(action or "-"), "idle"))[0]
def action_risk(action: Any) -> str:
"""action → 风险等级 key。"""
key = str(action or "").strip().lower()
return ACTION_LABELS.get(key, ("-", "idle"))[1]
def action_badge(action: Any) -> str:
"""action → 徽章 CSS 类。"""
key = str(action or "").strip().lower()
return RISK_LEVELS.get(action_risk(key), ("-", "muted"))[1]
def severity_label(severity: Any) -> str:
"""severity → 中文名。"""
key = str(severity or "").strip().lower()
return SEVERITY_LABELS.get(key, (str(severity or "-"), "muted"))[0]
def severity_badge(severity: Any) -> str:
"""severity → 徽章 CSS 类。"""
key = str(severity or "").strip().lower()
return SEVERITY_LABELS.get(key, ("-", "muted"))[1]
def engine_label(engine: Any) -> str:
"""engine → 中文名。"""
key = str(engine or "").strip().lower()
return ENGINE_LABELS.get(key, str(engine or "-"))
def mode_label(mode: Any) -> str:
"""mode → 中文名。"""
key = str(mode or "").strip().lower()
return MODE_LABELS.get(key, str(mode or "-"))
def category_label(category: Any) -> str:
"""category → 中文名。"""
key = str(category or "").strip().lower()
return CATEGORY_LABELS.get(key, str(category or "-"))
def channel_label(channel: Any) -> str:
"""channel → 中文名。"""
key = str(channel or "").strip().lower()
return CHANNEL_LABELS.get(key, str(channel or "-"))
def risk_label(risk: Any) -> str:
"""风险等级 key → 中文名。"""
key = str(risk or "").strip().lower()
return RISK_LEVELS.get(key, (str(risk or "-"), "muted", ""))[0]
def risk_badge(risk: Any) -> str:
"""风险等级 key → 徽章 CSS 类。"""
key = str(risk or "").strip().lower()
return RISK_LEVELS.get(key, ("-", "muted", ""))[1]
def risk_desc(risk: Any) -> str:
"""风险等级 key → 语义说明。"""
key = str(risk or "").strip().lower()
return RISK_LEVELS.get(key, ("-", "muted", ""))[2]
# =============================================================================
# 组合辅助
# =============================================================================
def risk_matrix() -> List[Dict[str, Any]]:
"""返回完整风险等级体系(供页面渲染说明表/图例)。"""
return [
{
"key": key,
"label": RISK_LEVELS[key][0],
"badge": RISK_LEVELS[key][1],
"desc": RISK_LEVELS[key][2],
}
for key in RISK_ORDER
if key in RISK_LEVELS
]
def verdict_summary(verdict_dist: Dict[str, int]) -> List[Dict[str, Any]]:
"""把 {verdict: count} 转成按风险等级聚合的展示列表。
输出按「高危 → 注意 → 故障 → 安全 → 处理中」排序,
每项含:中文名、徽章类、计数、占比、原始 verdict key。
同风险等级内的多个 verdict 会被合并(例如 malicious 与 reject 都是高危)。
"""
total = sum(verdict_dist.values()) or 0
# 先按 verdict 映射到风险等级
buckets: Dict[str, Dict[str, Any]] = {}
for v, cnt in verdict_dist.items():
risk = verdict_risk(v)
if risk not in buckets:
buckets[risk] = {
"key": risk,
"label": risk_label(risk),
"badge": risk_badge(risk),
"desc": risk_desc(risk),
"count": 0,
"verdicts": [],
}
buckets[risk]["count"] += int(cnt)
buckets[risk]["verdicts"].append(str(v))
items = list(buckets.values())
for it in items:
it["pct"] = round(it["count"] / total * 100, 1) if total else 0.0
items.sort(key=lambda x: RISK_ORDER.index(x["key"]) if x["key"] in RISK_ORDER else 99)
return items