Vicinious/scholar-threats
GitHub: Vicinious/scholar-threats
轻量级自托管CVE监控系统,通过基础设施相关性评分过滤噪音,仅推送对目标环境有实际影响的漏洞告警。
Stars: 0 | Forks: 0
# Scholar 威胁警报系统
[](package.json)
[](LICENSE)
[](package.json)
**面向基础设施安全团队的自动化威胁情报收集与警报系统。**
一个轻量级、自托管的 CVE 监控系统,它聚合来自权威来源(CISA KEV, NVD)的漏洞数据,应用感知基础设施的相关性评分,并通过 Discord webhook 传递可操作的警报。
## 目录
1. [摘要](#abstract)
2. [动机](#motivation)
3. [架构](#architecture)
4. [安装](#installation)
5. [配置](#configuration)
6. [用法](#usage)
7. [相关性评分算法](#relevance-scoring-algorithm)
8. [数据来源](#data-sources)
9. [数据库模式](#database-schema)
10. [部署](#deployment)
11. [API 参考](#api-reference)
12. [贡献](#contributing)
13. [许可证](#license)
## 摘要
Scholar 威胁警报系统解决了中小型基础设施安全中的一个关键缺口:缺乏自动化、降噪的漏洞监控。虽然企业级解决方案(Tenable, Qualys, Rapid7)提供了全面的覆盖,但它们引入了对于专注的基础设施环境而言不必要的复杂性和成本。
该系统实施了**相关性优先的过滤方法**:它不会针对所有漏洞发出警报,而是根据可配置的基础设施配置文件对每个 CVE 进行评分,仅显示对目标环境有实质性影响的漏洞。结果是实现了高信噪比,使安全团队能够应对真正的威胁而不会产生警报疲劳。
**主要差异化特性:**
- 对外部服务零运行时依赖(SQLite 本地存储)
- 历史查询延迟亚秒级
- 感知基础设施的评分(不仅仅是 CVSS)
- 集成 CISA KEV 以覆盖被积极利用的漏洞
- Discord 原生警报(无需邮件基础设施)
## 动机
### 问题
现代基础设施团队面临着一个不对称的挑战:NVD 每年发布约 20,000 个 CVE,但只有一小部分影响任何特定环境。如果没有自动过滤,团队必须:
1. **审查所有内容** —— 在规模上不可持续;导致倦怠并遗漏关键问题
2. **不审查** —— 接受未量化的风险;违反合规性要求
3. **使用企业工具** —— 引入成本、复杂性,通常还需要部署 Agent
### 解决方案
Scholar Threat Alerts 实施了一个**相关性评分管道**,它:
1. 从权威来源(CISA KEV, NVD)摄取 CVE
2. 通过 CPE 解析提取受影响的产品/供应商信息
3. 根据可配置的基础设施关键词集对每个 CVE 进行评分
4. 仅在分数超过可配置阈值时发出通知
5. 将低优先级警报聚合到定期摘要中
这种方法将每日警报量减少了 **85-95%**,同时保持对基础设施相关的关键漏洞 **100% 的覆盖率**。
## 架构
```
┌─────────────────────────────────────────────────────────────────────┐
│ DATA INGESTION │
├─────────────────┬─────────────────────────────────────────────────┬─┤
│ CISA KEV │ NVD CVE API │ │
│ (JSON Feed) │ (REST, rate-limited) │ │
└────────┬────────┴──────────────────────┬──────────────────────────┘ │
│ │ │
▼ ▼ │
┌─────────────────────────────────────────────────────────────────────┤
│ PROCESSING PIPELINE │
├─────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Fetcher │───▶│ Parser │───▶│ Relevance Scorer │ │
│ │ │ │ (CPE→Prods) │ │ (Infra Matching) │ │
│ └──────────────┘ └──────────────┘ └──────────┬───────────┘ │
│ │ │
│ ┌───────────▼───────────┐ │
│ │ Decision Engine │ │
│ │ score ≥ 7 → notify │ │
│ │ score 4-6 → digest │ │
│ │ score < 4 → log │ │
│ └───────────┬───────────┘ │
└──────────────────────────────────────────────────────┼──────────────┘
│
┌─────────────────────────────────────────────┴──────┐
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ SQLite Store │ │ Discord Webhook │
│ ┌───────────────┐ │ │ │
│ │ alerts │ │ │ • Immediate alerts │
│ │ seen_cves │ │ │ • Weekly digests │
│ │ digest_queue │ │ │ │
│ └───────────────┘ │ └─────────────────────┘
└─────────────────────┘
```
### 组件职责
| 组件 | 职责 | 实现 |
|-----------|---------------|----------------|
| **Fetcher** | 带速率限制的 HTTP 检索 | `src/fetcher.js` |
| **Parser** | CPE 字符串 → 产品列表提取 | `src/fetcher.js` |
| **Scorer** | 基础设施相关性计算 | `src/scorer.js` |
| **Notifier** | Discord webhook 格式化/交付 | `src/notifier.js` |
| **Store** | 持久化、去重、历史记录 | `src/db.js` |
## 安装
### 前置条件
- Node.js ≥ 18.0.0
- npm 或 yarn
- SQLite3(通过 better-sqlite3 包含)
### 快速开始
```
# 克隆 repository
git clone https://github.com/Vicinious/scholar-threats.git
cd scholar-threats
# 安装 dependencies
npm install
# 创建 data directory
mkdir -p data
# 运行 initial check
./bin/scholar-threats check
```
### 系统级安装
```
# 全局链接 binary
sudo ln -sf $(pwd)/bin/scholar-threats /usr/local/bin/scholar-threats
# 验证 installation
scholar-threats help
```
## 配置
### Discord Webhook
创建一个 webhook 配置文件:
```
echo "https://discord.com/api/webhooks/YOUR/WEBHOOK" > /path/to/discord-webhook-alerts.txt
```
在 `src/notifier.js` 中更新路径:
```
const WEBHOOK_PATH = '/path/to/discord-webhook-alerts.txt';
```
### 基础设施关键词
修改 `src/scorer.js` 以匹配您的环境:
```
const INFRA_KEYWORDS = {
high: ['nginx', 'ssh', 'mysql', 'node', 'ubuntu', 'linux'], // Your core stack
medium: ['npm', 'api', 'tls', 'ssl', 'dns', 'http'], // Supporting tech
low: ['windows', 'iis', 'azure', 'aws'] // Irrelevant platforms
};
```
### 评分阈值
`src/index.js` 中的默认阈值:
| 分数 | 动作 | 理由 |
|-------|--------|-----------|
| ≥ 7 | 立即 Discord 警报 | 相关性置信度高 |
| 4-6 | 包含在每周摘要中 | 可能值得关注 |
| < 4 | 仅记录日志(不通知) | 可能不相关 |
## 用法
### 命令
```
# 获取并处理新 CVE
scholar-threats check
# 列出近期 alerts(默认:7 天)
scholar-threats list [days]
# 预览 weekly digest
scholar-threats digest --preview
# 立即发送 weekly digest
scholar-threats digest
# 显示未通知的 high-priority alerts
scholar-threats pending
# 显示帮助
scholar-threats help
```
### 示例
```
# 检查 feeds 并 alert 新的 high-priority CVE
$ scholar-threats check
=== Scholar Threat Check ===
Time: 2026-03-14T21:31:57.620Z
Fetching CISA KEV catalog...
CISA KEV: 24 recent entries
Fetching NVD CVEs from last 24 hours...
NVD: 47 CVEs from last 24h
Results:
New alerts stored: 12
High priority notified: 2
# 列出过去 14 天的 alerts
$ scholar-threats list 14
=== Alerts from last 14 days ===
CRITICAL (9) CVE-2026-12345 [KEV] ✓
nginx buffer overflow in HTTP/2 module...
HIGH (7) CVE-2026-12346 [KEV] ✓
OpenSSH authentication bypass via crafted key...
HIGH (6) CVE-2026-12347
MySQL privilege escalation in stored procedures...
```
## 相关性评分算法
评分算法平衡了**严重性**(源自 CVSS)与**相关性**(特定于基础设施):
```
Score = BaseSeverity + InfraBonus + CVSSBonus + KEVBonus - IrrelevancePenalty
```
### 评分组成部分
| 组成部分 | 分值 | 触发条件 |
|-----------|-------|---------|
| **BaseSeverity** | 1-4 | CRITICAL=4, HIGH=3, MEDIUM=2, LOW=1 |
| **InfraBonus (High)** | +3 | 匹配高优先级关键词 |
| **InfraBonus (Medium)** | +2 | 匹配中优先级关键词 |
| **CVSSBonus** | +1 | CVSS ≥ 9.0 |
| **KEVBonus** | +3 | 存在于 CISA KEV 目录中 |
| **IrrelevancePenalty** | -2 | 仅匹配低优先级关键词 |
### 计算示例
**CVE-2026-12345: nginx 缓冲区溢出, CVSS 9.8, 在 KEV 中**
```
Base: 4 (CRITICAL)
+ Infra High (nginx): +3
+ CVSS ≥ 9.0: +1
+ KEV: +3
= Score: 11 → IMMEDIATE ALERT
```
**CVE-2026-12346: Windows NTFS 损坏, CVSS 7.5**
```
Base: 3 (HIGH)
+ Infra Low (windows): -2
= Score: 1 → LOG ONLY (no notification)
```
## 数据来源
### CISA 已知被利用漏洞 (KEV)
- **URL:** `https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json`
- **更新频率:** 每日
- **描述:** 已确认被积极利用的漏洞的权威目录
- **重要性:** KEV 存在表明现实世界中存在威胁行为者活动
### NIST 国家漏洞数据库 (NVD)
- **URL:** `https://services.nvd.nist.gov/rest/json/cves/2.0`
- **更新频率:** 持续(建议每小时检查)
- **速率限制:** 无 API key 时 30 秒内 5 个请求
- **描述:** 包含 CVSS 分数和 CPE 映射的综合 CVE 存储库
## 数据库模式
```
-- Primary alert storage
CREATE TABLE alerts (
id INTEGER PRIMARY KEY,
cve_id TEXT UNIQUE, -- CVE-YYYY-NNNNN
title TEXT, -- Vulnerability description
severity TEXT, -- CRITICAL/HIGH/MEDIUM/LOW
cvss_score REAL, -- Numeric CVSS (0.0-10.0)
affected_products TEXT, -- JSON array of product strings
relevance_score INTEGER, -- Calculated infrastructure score
in_kev BOOLEAN DEFAULT FALSE, -- CISA KEV presence
first_seen_at TEXT, -- ISO8601 timestamp
notified_at TEXT, -- When Discord alert sent (null if not)
resolved_at TEXT, -- When marked resolved (optional)
resolution_notes TEXT -- Remediation notes (optional)
);
-- Deduplication tracking
CREATE TABLE seen_cves (
cve_id TEXT PRIMARY KEY,
first_seen_at TEXT
);
-- Weekly digest queue
CREATE TABLE digest_queue (
id INTEGER PRIMARY KEY,
alert_id INTEGER REFERENCES alerts(id),
added_at TEXT,
included_in_digest TEXT -- ISO8601 of digest that included this
);
```
## 部署
### Systemd 服务(可选)
对于生产部署,创建一个 systemd 定时器:
```
# /etc/systemd/system/scholar-threats.service
[Unit]
Description=Scholar Threat Alert Check
After=network.target
[Service]
Type=oneshot
User=openclaw
WorkingDirectory=/srv/openclaw-shared/scholar-threats
ExecStart=/opt/node/bin/node bin/scholar-threats check
StandardOutput=append:/var/log/scholar-threats.log
StandardError=append:/var/log/scholar-threats.log
```
```
# /etc/systemd/system/scholar-threats.timer
[Unit]
Description=Run Scholar Threat Alerts every 4 hours
[Timer]
OnCalendar=*-*-* 00/4:00:00
Persistent=true
[Install]
WantedBy=timers.target
```
### Cron(推荐)
```
# /etc/cron.d/scholar-threats
0 */4 * * * openclaw cd /srv/openclaw-shared/scholar-threats && /opt/node/bin/node bin/scholar-threats check >> /tmp/openclaw/scholar-threats.log 2>&1
0 8 * * 0 openclaw cd /srv/openclaw-shared/scholar-threats && /opt/node/bin/node bin/scholar-threats digest >> /tmp/openclaw/scholar-threats.log 2>&1
```
## API 参考
### 模块导出 (`src/index.js`)
```
import { check, list, digest, pending } from './src/index.js';
// Fetch and process new CVEs
await check();
// Returns: { newAlerts: number, highPriorityNotified: number }
// List recent alerts
const alerts = await list(7); // Last 7 days
// Returns: Alert[]
// Generate/send digest
await digest(true); // Preview only
await digest(false); // Send to Discord
// Returns: Alert[]
// Get unnotified high-priority alerts
const pending = await pending();
// Returns: Alert[]
```
### 警报对象模式
```
interface Alert {
id: number;
cve_id: string;
title: string;
severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
cvss_score: number;
affected_products: string; // JSON array
relevance_score: number;
in_kev: boolean;
first_seen_at: string;
notified_at: string | null;
resolved_at: string | null;
resolution_notes: string | null;
}
```
## 贡献
1. Fork 本仓库
2. 创建一个特性分支 (`git checkout -b feature/improvement`)
3. 提交更改 (`git commit -am 'Add improvement'`)
4. 推送到分支 (`git push origin feature/improvement`)
5. 发起一个 Pull Request
### 代码风格
- ES Modules (`import`/`export`)
- 所有 I/O 使用 Async/await
- 公共函数使用 JSDoc 注释
- 无外部 HTTP 客户端(使用原生 `fetch`)
## 许可证
MIT 许可证 —— 详情见 [LICENSE](LICENSE)。
## 致谢
- [CISA](https://www.cisa.gov/) 提供 KEV 目录
- [NIST NVD](https://nvd.nist.gov/) 提供 CVE 数据
- [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) 提供 SQLite 绑定
*由 Kevin, Hand of the King 🦉 构建 —— 因为手动检查 CVE 源是平民干的事。*
标签:CISA KEV, Discord机器人, GNU通用公共许可证, GPT, MITM代理, Node.js, NVD, PB级数据处理, SQLite, 企业安全, 信噪比优化, 威胁情报, 安全运维, 密码管理, 开发者工具, 无线安全, 漏洞管理, 网络安全, 网络安全审计, 网络资产管理, 自动化告警, 自定义脚本, 自托管, 轻量级工具, 隐私保护