ryanshrier/blueteam

GitHub: ryanshrier/blueteam

一款面向网络防御团队的自托管威胁情报平台,将公开威胁报告自动聚合、评分富化,并以大屏态势展示、分析师工作区和AI每日简报三种形式呈现。

Stars: 3 | Forks: 0

# BlueTeam.News [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/ryanshrier/blueteam/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) ![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen) **BlueTeam.News 是一个为网络防御团队设计的自托管威胁情报平台。** 它将公开的威胁报告进行分组和富化,通过可见的证据对每个信号进行优先级排序,并将结果呈现为: - **The Wall** — 用于运营显示屏的被动态势感知 - **The Wire** — 带有评分证据、KEV、CVSS、EPSS 和归属标签的可过滤分析师订阅源 - **The Briefing** — AI 生成的综合层:面向防御者和领导层的每日评估(需要 Anthropic 密钥) The Wall 和 Wire 无需任何 API 密钥即可运行。为了获得完整的每日体验——包括 BLUF、判断、行动以及面向领导层的综合分析——请接入 Anthropic 密钥并启用 Briefing。数据本地存储在 SQLite 中,且应用程序不发送任何遥测数据。 *为前线打造,以证据为基础。坚守防线。* **[快速开始](#quick-start) · [The Wall](#the-wall) · [The Wire](#the-wire) · [The Briefing](#the-briefing) · [层级](#the-three-tiers) · [架构](#architecture) · [配置](#configuration) · [API](#api) · [安全](#security-posture) · [开发](#development)** ## 快速开始 ``` git clone https://github.com/ryanshrier/blueteam.git blueteam && cd blueteam npm install npm start ``` 打开 [http://127.0.0.1:3000](http://127.0.0.1:3000)。随着首批数据源响应到达,The Wall 和 Wire 将开始填充,此过程无需任何配置或 API 密钥。 为了获得完整的每日体验,请在 **Settings** 或 `.env` 中填入 Anthropic API 密钥,以启用推荐的 AI Briefing: ``` cp .env.example .env # 添加 ANTHROPIC_API_KEY=sk-ant-... npm start ``` 您可以按需生成。服务器还会在**本地时间 05:00** 自动刷新其证据并创建一个新版本;错过的运行将在重启后自动补齐,失败的任务每 15 分钟重试一次。每次成功的计划生成或手动生成都将直接计入您的 Anthropic 账单。BlueTeam.News 会报告模型、token 数量以及估算的 API 成本。 ### 放到展示墙上 在驱动屏幕的机器上运行 BlueTeam.News——例如电视背后的迷你 PC 或 Raspberry Pi,或者使用您自己的笔记本电脑外接第二台显示器,然后打开: ``` http://127.0.0.1:3000/wall ``` `/wall` 是被动展示路由,会自动隐藏鼠标指针;按 `Esc` 键退出。无密钥模式下会展示 KEV 变更和优先级信号。启用 Briefing 后,The Wall 会在无需操作员干预的情况下,自动采用每个完整的每日版本。其预期部署方式是保持在 loopback 上,由主机驱动或镜像显示。 ## The Wall 把它放在电视上。路过看一眼。了解全局。 ![The Wall 的 wire 页面 —— 评分后的信号排列成大版面行](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/99e29df2cd6afaa1a865bfbf4bd35272a79e85cc7c45ac6377e7f3f50881d139.jpg) *轮播中的 wire 页面 —— 最新评分的信号,排列成可在十英尺外看清的格式。* The Wall 为运营显示屏提供被动的态势感知。其值班大版面会轮播最新简报、关键判断、发展中的态势、情报融合、KEV 变更和优先级信号。 - **The Briefing** — BLUF 以及最新 AI 简报的“摘要”集锦 - **Key Judgments** — 每页一个核心判断,带有精炼的“结论”、置信度和决策窗口 - **Developing + Convergence** — 正在发生变化的事件、可能导致事态升级的因素,以及不同信号结合后引发的更大防御后果 - **KEV changes** — 最新确认被利用的目录新增项 - **The Wire** — 实时评分的信号,排列成列对齐的行:层级 · 标题 + 要点 · 严重程度 (KEV / CVSS) · 时效,并标记出最新内容 打开 `/wall` 即可作为无人值守的展示屏。它会自动隐藏鼠标指针;按 `Esc` 键退出。配置了 Anthropic 密钥后,服务器会在本地时间 05:00 生成新简报,The Wall 会自动采用它。无需 WebGL 或 canvas——只需一个浏览器。 ## The Wire The Wire 是分析师的工作区:包含最新 pipeline 运行中的所有优先级信号,以及其背后的评分证据。可按层级、紧急程度、KEV 状态和未读状态进行过滤;检查来源广度、CVSS 和 EPSS 数据、归属标签、时间戳和 CVE 详情;并将结果导出为 CSV 或 JSON。 打开 `/wire`;过滤后的视图会将其状态保存在可共享的查询字符串中,例如 `/wire?kev=1&sort=newest`。 ![The Wire —— 带有过滤器和证据标签的所有评分信号](https://static.pigsec.cn/wp-content/uploads/repos/cas/56/56152fbfb8cd771291d6f2a7a0be36bba10aa24b6ec5ff63297e64a1146cae8c.png) *The Wire 的真实截图:顶部是聚合事件的轮播条,随后是每个信号及其评分和背后的证据。* ## The Briefing The Briefing 为分析师和领导层提供了一幅共享的威胁图景:BLUF、校准后的判断、防御行动、发展中的态势、情报融合以及 72 小时观察名单。 打开 `/briefing`;归档的简报在 `/briefing/` 具有持久链接。 生成过程支持按需执行,并在每天本地时间 05:00 自动运行一次。它通过 SSE 流式传输,在存储前进行结构验证,归档为 Markdown,并在 SQLite FTS5 中建立索引。计划任务的成功状态会被持久化,以防止在重启后产生重复的每日费用;错过的任务会自动补齐,失败的任务会重试。每份简报都被标记为 AI 生成,并带有常驻的“行动前需验证”警告。 ![The Briefing —— 一份由 AI 撰写的每日威胁简报,带有其专属的诚实声明框](https://static.pigsec.cn/wp-content/uploads/repos/cas/2d/2d9e6ad0c0e99d1ee3a781343620a4f01514825600ed42176e757232a1545493.png) *真实截图 —— 包括指出了简报自身缺陷的验证框。每份简报都被标记为 AI 生成,并在屏幕和导出文件中带有常驻的“行动前需验证”警告;其生成过程基于当天的评分信号以及确定性的 KEV 事实区块,如果发生结构性硬故障,将触发一次纠正性重试。* ## 三个层级 BlueTeam.News 将每个信号分为三个 CTI 层级之一 —— 战术 / 战役 / 战略金字塔,该金字塔驱动着评分、UI、The Wall 和简报: | 层级 | 名称 | 时间窗口 | 读者 | 回答的问题 | |---|---|---|---|---| | **T1** | Tactical (战术) | 当前班次至 7 天 | SOC · IR · 检测 | 在下一次换班前,有什么需要引起重视? | | **T2** | Operational (战役) | 未来几周至 12 个月 | 威胁狩猎 · 情报 · 安全工程 | 哪些发展中的威胁活动、能力、暴露或策略变更需要进行防御调整? | | **T3** | Strategic (战略) | 12 个月以上 | 总监 · CISO · 董事会 | 哪些结构性变化将实质性地改变威胁环境、防御模型或风险态势? | 这些层级对应着情报的消费者:SOC 侧重于 Tactical,威胁狩猎和情报侧重于 Operational,领导层侧重于 Strategic。简报有意为这三类人群提供服务:每个信号都带有分析师级别的具体细节(CVE、版本、行动)*以及*总监可以带入会议的一句话判断。 ## 架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ Browser (vanilla ES modules) │ │ Briefing · Wire · Wall (watchfloor broadsheet) │ └───────────────────────────┬─────────────────────────────────┘ │ REST + SSE ┌───────────────────────────▼─────────────────────────────────┐ │ Express (server.js) │ │ routes/brief (SSE generation, history, FTS5 search) │ │ routes/landscape (wall payload, wire headlines, refresh) │ └──────┬──────────────────┬──────────────────┬────────────────┘ │ │ │ lib/feeds lib/landscape lib/prompts lib/scoring lib/refresher lib/history lib/enrichment lib/db (SQLite + FTS5) │ RSS/Atom feeds · Google News · CISA KEV · NVD Claude API (no keys required) (Anthropic key) ``` **Pipeline** (`lib/feeds.js`) 按计划(默认:每 10 分钟)和按需运行: 1. 获取配置的 RSS/Atom 源(有界并发、条件 GET、每个源独有的熔断器)以及新闻搜索扫描 2. 使用 TF-IDF 余弦相似度对相似的事件进行分组,并记录有多少个不同的配置源对其进行了报道 —— 这体现了有用的来源多样性,但并不能证明这些报道是独立的 3. 对紧急程度进行分类,应用告警规则权重提升和配置覆盖,并将具有战役紧急性的项目提升至 Tactical 层级 4. 使用 CISA KEV 成员资格以及实体和 MITRE ATT&CK 标签对每个候选项进行预富化,以便已验证的漏洞利用能够影响选择 5. 从五个加权维度进行评分 —— 时效性、来源多样性、漏洞利用、严重性和相关性 —— 然后强制执行每层下限和每源上限,这样单个嘈杂的源就无法淹没整体态势 6. 对选定的集合进行后富化,添加 NVD CVSS 详情、文章提取、EPSS 和指标 7. 使用已验证的富化证据重新评分和排序;每个评分组件保持可检查和可调整 结果归档在 SQLite 中(滚动窗口)以支持趋势分析:攻击者排行榜和头条速度。 **Briefing** (`routes/brief.js`) 通过 SSE 流式传输 Claude 的输出,具备超时恢复和模型回退功能,验证结构(BLUF、判断、融合、观察名单),将 Markdown 保存到 `briefs/`,并在 SQLite FTS5 中建立索引以进行全文搜索。 ## 配置 所有内容都通过 `config.json` 进行调整(保存时热重载,使用 Zod 验证): | 区块 | 控制内容 | |---|---| | `organization` | 简报的可选上下文:团队简介、所属行业、关注主题和地区 | | `horizons` | 三个层级的名称、时间窗口和核心问题 | | `trustedFeeds` | 带有层级、权重和深度提取标志的 RSS/Atom 源 | | `alertRules` | 用于提升匹配头条(零日漏洞、勒索软件、您技术栈中的供应商等)权重的正则表达式 | | `analysisSettings` | 模型、token 预算、刷新频率、时效窗口、层级权重、评分调试以及可选的告警 `webhook` | 想要为您定制的环境生成简报?请将您的技术栈添加到 `alertRules` 和 `organization.watchTopics` 中: ``` "organization": { "sector": "Financial services", "watchTopics": ["payment fraud", "SWIFT", "core banking platforms"] }, "alertRules": [ { "pattern": "Okta|Entra|Workday", "boost": 4 } ] ``` ### 告警 webhook(可选) `analysisSettings.webhook` 可以在每次 pipeline 运行后、每日 Briefing 完成后推送匹配告警的信号,或两者兼有。它**默认禁用** —— 空的 `url` 意味着不会发出任何请求: ``` "analysisSettings": { "webhook": { "url": "", "format": "slack", "events": "alerts" } } ``` 将 `url` 设置为您的传入 webhook endpoint 以启用它。`format` 可以是 `slack`(兼容 Slack/Teams 的消息)或 `json`。将 `events` 设置为 `alerts`(默认)、`brief` 或 `both`。告警推送仅包含匹配 `alertRule` 的信号,且每个事件最多触发一次;简报推送会发送已完成版本的日期、BLUF、关键判断和深链接。当接收者需要通过公共部署打开该链接时,请设置 `PUBLIC_BASE_URL`;否则它会安全地指向 `http://localhost:PORT`。出站请求像所有其他抓取请求一样受到 SSRG 防护。推送采用尽力而为策略:失败的 webhook 会被记录,但绝不会阻塞 pipeline 的运行或简报的保存。 ## 环境变量 | 变量 | 必需 | 描述 | |---|---|---| | `ANTHROPIC_API_KEY` | 否 | 启用 AI 简报生成(接受 `ANTHROPIC_API_KEY_PRIMARY` 作为别名) | | `ANTHROPIC_API_KEY_SECONDARY` | 否 | 认证失败时自动回退 | | `NVD_API_KEY` | 否 | 提高 NVD CVE 查找的速率限制(5 → 50 次请求 / 30秒)。[免费密钥。](https://nvd.nist.gov/developers/request-an-api-key) | | `BLUETEAM_USER_AGENT` | 否 | 覆盖指定的订阅源阅读器标识,例如添加您组织的联系 URL。 | | `PORT` | 否 | HTTP 端口(默认为 `3000`) | | `HOST` | 否 | 绑定地址(默认为 `127.0.0.1`)。BlueTeam.News 旨在运行于驱动显示屏的机器上,因此 loopback 是其预期的部署方式。 | | `PUBLIC_BASE_URL` | 否 | 用于 RSS/JSON 源元数据和已完成简报 webhook 链接的标准 HTTP(S) 源,例如 `https://blueteam.news`。仅限源:凭据、路径、查询和片段在启动时会被拒绝。未设置时,将保留从请求中派生的本地源 URL 以及安全的 `http://localhost:PORT` webhook 回退。 | | `API_SECRET` | 否 | 在 `/api/*` 上进行 Bearer token 认证。如果没有它,服务器将拒绝绑定非 loopback 的 `HOST` —— 这是一个故障关闭防护,确保偶然 `HOST=0.0.0.0` 不会悄无声息地暴露 API。 | | `ENABLE_EMBED` | 否 | 只要设置了 `API_SECRET`,`/embed`(无需密钥的 iframe 小部件)默认就会禁用,因为它无法携带 Bearer token。在锁定的部署中,可将其设置为 `1` 以重新选择启用。 | | `CORS_ORIGIN` | 否 | 允许的源(默认:同源) | | `TRUST_PROXY` | 否 | 在反向代理(nginx, Caddy, Cloudflare)后运行时设置 —— 可以是跳数(例如 `1`)或子网/`loopback`。只有在设置后,`X-Forwarded-*` 标头才会被用于速率限制、客户端 IP 以及未设置 `PUBLIC_BASE_URL` 时从请求派生的源 URL;否则它们将被忽略,防止直接连接的客户端伪造它们。 | | `NODE_ENV` | 否 | `production` 启用 JSON 日志 + HSTS | ## API | Endpoint | 方法 | 描述 | |---|---|---| | `/api/landscape` | GET | 完整的 Wall 载荷:信号、KEV、攻击者、速度 | | `/api/headlines` | GET | 最新 pipeline 运行中的所有评分头条 | | `/api/feed.xml` | GET | 顶级评分信号(标题、链接、来源、层级、评分、KEV)的 RSS/Atom 源 | | `/api/feed.json` | GET | 相同顶级评分信号的 [JSON Feed](https://www.jsonfeed.org/) | | `/api/briefs.xml` | GET | 每日简报本身的 RSS 2.0 源 | | `/api/refresh` | POST | 强制运行 pipeline | | `/api/brief` | POST | 生成简报(SSE 流) | | `/api/briefs` | GET | 简报历史记录 | | `/api/brief/:filename` | GET | 特定的简报 | | `/api/search?q=` | GET | 对所有简报进行全文搜索 (SQLite FTS5) | | `/api/health` | GET | 数据源、pipeline、数据库、内存和 AI 的状态 | | `/api/edition` | GET | 活动 CTI 配置文件的身份标识(id、标题、标签、地区) | | `/api/settings` | GET / POST | 读取/更新本地组织上下文和关注词汇;读取掩码后的 AI 密钥状态,或在运行时设置/清除密钥 | | `/api/settings/verify` | POST | 进行一次低成本的 Anthropic 调用,以确认密钥确实有效 | | `/embed` | GET | 无需密钥、无页眉的 HTML 信号条,用于嵌入 `