tasox/ti-agent

GitHub: tasox/ti-agent

一款 AI 驱动的威胁情报简报工具,自动抓取并分析安全 RSS 订阅源,借助 Claude 生成带可溯源引用的结构化分析报告。

Stars: 0 | Forks: 0

# TI Agent — AI 驱动的威胁情报简报工具 TI Agent 是一个全栈本地应用程序,它从 RSS/Atom 订阅源中获取真实的安全文章,将其传递给 Claude 进行分析,并生成包含内联引用的结构化威胁情报简报,引用可直接链接到源文章。 与那些仅仅将订阅源 URL 提供给 LLM 并祈祷好运的工具不同,TI Agent 会在服务端实际获取并解析订阅源,根据您选择的日期窗口过滤文章,并将真实内容发送给 Claude。报告中的每一个声明都可以追溯到特定的文章,并且每个 `[N]` 引用都是指向该文章 URL 的可点击链接。 ![alt text](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/5d85041865095214.png) ## 功能 - **97 个内置安全订阅源**,分为 6 个类别:IOC 订阅源、漏洞、威胁情报、红|蓝|紫队、安全新闻、CTF 与学习 - **真正的 RSS/Atom 获取** — 在服务端获取并解析文章,并在 Claude 处理之前根据您的日期窗口进行过滤 - **内联引用** — 报告中的每一个事实性声明后面都带有指向源文章的 `[N]` 徽章 - **权威参考文献部分** — 生成后从实际的源映射中重建,确保完整性且无重复 - **4 种导出格式** — Markdown(带有超链接引用)、HTML、PDF(深色主题,可直接打印)、DOCX(标准的基于 ZIP 的 `.docx`) - **成本追踪与预测** — 单次运行的 token 用量、实际与预估成本的准确性、30 天预算预测 - **完全持久化** — 所有报告、配置和自定义订阅源均保存至 SQLite;在服务端重启后依然存在 - **自定义订阅源** — 添加任何带有名称和类别的 RSS/Atom 订阅源 URL - **订阅源管理** — 启用、禁用或永久删除任何订阅源(内置或自定义) - **配置导出/导入** — 以 JSON 格式快照并恢复您的整个配置 - **4 种 Claude 模型** — Haiku 4.5(默认)、Sonnet 4.5、Sonnet 4.6、Opus 4.5 ## 工作原理 ``` ┌─────────────────────────────────────────────────────────┐ │ Browser (React) │ │ CONFIG tab → select feeds, date window, model, focus │ │ │ │ │ Click "Generate Briefing" │ └────────────────────────┬────────────────────────────────┘ │ POST /api/fetch-feeds ▼ ┌─────────────────────────────────────────────────────────┐ │ Express Server :3001 │ │ │ │ 1. Fetch all selected feeds in parallel (8s timeout) │ │ 2. Parse RSS 2.0 / Atom 1.0 XML │ │ 3. Filter articles to date window │ │ 4. Cap at 15 articles per feed │ │ 5. Return { articles[], errors[] } │ └────────────────────────┬────────────────────────────────┘ │ articles arrive in browser │ POST /api/analyze ▼ ┌─────────────────────────────────────────────────────────┐ │ Express Server :3001 │ │ │ │ Proxy to Anthropic API with prompt containing: │ │ - Numbered article list [1]..[N] with title/URL/date/ │ │ summary for each article │ │ - Citation rule: cite [N] after every claim │ │ - Structured report sections │ └────────────────────────┬────────────────────────────────┘ │ Claude response ▼ ┌─────────────────────────────────────────────────────────┐ │ Browser (React) │ │ │ │ - rebuildReferences() strips Claude's References │ │ section and rebuilds it from the source map │ │ - renderMarkdown() renders [N] as clickable links │ │ - Report saved to SQLite with source_map JSON │ └─────────────────────────────────────────────────────────┘ ``` ### 报告部分 每份报告都遵循以下结构: | # | 部分 | 描述 | |---|---------|-------------| | 1 | Data Window | 涵盖的日期范围和文章数量 | | 2 | Executive Summary | 3-4 句 CISO 级别的摘要及引用 | | 3 | Top Threats | 最多 5 个排名的威胁 (CRITICAL / HIGH / MEDIUM) | | 4 | IOC Highlights | 仅包含文章中真实的 IOC — IP、域名、哈希值 | | 5 | CVE Watch | 以表格格式明确提及的 CVE | | 6 | Threat Actor Spotlight | 具名的攻击者及其 TTP 和 MITRE ID | | 7 | Analyst Recommendations | 3 个可操作的步骤 | | 8 | MITRE ATT&CK Coverage | 表格格式的技术列表 | | 9 | References | 完整且去重的引用文章列表 | ## 要求 | 要求 | 版本 | 备注 | |-------------|---------|-------| | Node.js | **22.x** | Express 4 在 Node 22 上会崩溃 — 必须使用 Node 22 | | macOS | 12+ | 已在 macOS 上测试;兼容 Linux;Windows 未测试 | | Anthropic API key | — | `sk-ant-api03-...` 格式 | | Xcode CLI tools | — | 编译 `better-sqlite3` 本地构建所需 | ## 依赖项 ### 运行时 (npm) | 包 | 版本 | 用途 | |---------|---------|---------| | `express` | `^5.x` | HTTP 服务器和路由。**必须是 v5 版本** — Express 4 与 Node 22 内置的 `path-to-regexp` 不兼容 | | `cors` | `^2.x` | 跨域标头,以便运行在 :3000 上的 React 开发服务器可以调用 :3001 | | `node-fetch` | `@2.x` | 用于获取 RSS 订阅源和代理至 Anthropic 的 HTTP 客户端。**必须是 v2 版本** — v3 仅支持 ESM,与 CommonJS 的 `require()` 不兼容 | | `better-sqlite3` | `^9.x` | 同步 SQLite 驱动程序。需要本地构建工具(macOS 上的 Xcode CLI) | ### 内置 (Node.js — 无需安装) | 模块 | 用于 | |--------|---------| | `path` | 解析相对于 `server.js` 的数据库文件路径 | | `fs` | 启动时数据库文件状态检查 | | `zlib` | `deflateRawSync` 用于构建有效的 `.docx` ZIP 归档 | ### 前端 (包含在 Create React App 中) | 包 | 用途 | |---------|---------| | `react` | UI 框架 | | `react-dom` | DOM 渲染 | | `react-scripts` | CRA 构建工具链、开发服务器、Babel | ### 外部服务 | 服务 | 用于 | |---------|---------| | Anthropic API | Claude 推理 (`/v1/messages`) — 通过本地服务器代理,API key 绝不存储在磁盘上 | | Google Fonts(可选) | HTML/PDF 导出中的 IBM Plex Mono 字体 — 离线时回退到 Courier New | ## 安装说明 ### 1. 前置条件 ``` # macOS — 安装 Xcode command line tools(better-sqlite3 必需) xcode-select --install # 如果尚未安装,通过 Homebrew 安装 Node 22 brew install node node --version # should print v22.x.x ``` ### 2. 克隆仓库 ``` git clone https://github.com//ti-agent.git cd ti-agent ``` ### 3. 安装依赖 该仓库附带了一个现成的 `package.json`,涵盖了前端和后端的所有依赖: ``` npm install ``` 这一步将一次性安装 `react`、`react-dom`、`react-scripts`、`express@5`、`cors`、`node-fetch@2` 和 `better-sqlite3`。 ### 4. 项目位置 **重要提示:** 请勿将项目放在 iCloud Drive (`~/Library/Mobile Documents/`) 内。iCloud 的同步机制会干扰 SQLite 的 WAL 日志文件,并可能导致数据库损坏或数据库文件不可见。请将其克隆到本地路径,例如 `~/Projects/ti-agent`。 ## 运行说明 ![alt text](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/8b445987f7095223.png) 在项目目录中打开两个终端窗口: ``` # Terminal 1 — backend(端口 3001) node server.js ``` 您应该会看到: ``` 📂 DB path: /Users/you/Downloads/ti-agent/ti-agent.db 📦 DB file size: 32768 bytes 📦 Database ready at /Users/you/Downloads/ti-agent/ti-agent.db ✅ TI Agent server → http://localhost:3001 ``` ![alt text](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/836286c343095225.png) ``` # Terminal 2 — frontend(端口 3000) npm start ``` ![alt text](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/75eb6f92df095230.png) 在浏览器中打开 **http://localhost:3000**。 ## 首次运行 1. 转到 **⚙ CONFIG** 标签页 2. 输入您的 Anthropic API key — 它仅保存在内存中,并在每次页面刷新时清除,绝不写入磁盘 3. 选择您的订阅源和日期窗口 4. 点击 **⚡ GENERATE BRIEFING** 按钮标签将循环显示两个阶段: - `◌ FETCHING N FEEDS…` — 正在下载并解析 RSS/Atom 订阅源 - `◌ ANALYZING WITH AI…` — Claude 正在处理文章 ## 数据库 SQLite 数据库 (`ti-agent.db`) 会在首次运行时自动在 `server.js` 所在的目录中创建。它包含三个表: ### `config` 用于存储所有 UI 偏好设置的键/值存储。值均已进行 JSON 序列化。 | 键 | 类型 | 描述 | |-----|------|-------------| | `selectedIds` | `string[]` | 选择用于分析的订阅源 ID | | `selectedModelId` | `string` | 当前生效的 Claude 模型 | | `query` | `string` | 分析焦点 prompt | | `schedule` | `string` | 计划任务偏好标签 | | `maxTokens` | `number` | Claude 最大输出 token 数量 | | `datePreset` | `number` | 日期预设数组的索引 | | `customFrom` / `customTo` | `string` | 自定义日期范围 (YYYY-MM-DD) | | `disabledIds` | `string[]` | 暂时禁用的订阅源 | | `deletedIds` | `string[]` | 永久删除的订阅源 | ### `custom_feeds` 用户添加的 RSS/Atom 订阅源。 | 列 | 类型 | 描述 | |--------|------|-------------| | `id` | TEXT PK | 唯一标识符 | | `name` | TEXT | 显示名称 | | `xmlUrl` | TEXT | RSS/Atom 订阅源 URL | | `url` | TEXT | 人类可读的网站 URL | | `category` | TEXT | 订阅源类别 | | `color` | TEXT | UI 的十六进制颜色代码 | | `created_at` | TEXT | ISO 时间戳 | ### `reports` 生成的简报及其完整元数据。 | 列 | 类型 | 描述 | |--------|------|-------------| | `id` | INTEGER PK | 自动递增 | | `timestamp` | TEXT | 人类可读的生成时间 | | `query` | TEXT | 所使用的分析焦点 | | `date_from` / `date_to` | TEXT | 日期窗口 | | `sources` | INTEGER | 选择的订阅源数量 | | `model_id` / `model_name` | TEXT | 所使用的 Claude 模型 | | `input_tokens` / `output_tokens` | INTEGER | 实际 token 使用量 | | `input_cost` / `output_cost` / `total_cost` | REAL | 实际花费(美元) | | `est_input_tok` / `est_output_tok` / `est_total_cost` | REAL | 执行前预估 | | `body` | TEXT | 完整的 Markdown 报告 | | `source_map` | TEXT | 用于引用的 JSON 映射 `{"1": {name, url}, ...}` | | `created_at` | TEXT | ISO 时间戳 | ### 数据迁移 服务器在启动时运行非破坏性迁移。向 schema 添加列不会破坏现有数据库 — `ALTER TABLE` 语句被包裹在 `try/catch` 中,因此已存在的列会被静默跳过。 ## API 参考 所有 endpoint 均位于 `http://localhost:3001`。 | 方法 | 路径 | 描述 | |--------|------|-------------| | `GET` | `/health` | 服务器健康检查,返回数据库路径 | | `POST` | `/api/fetch-feeds` | 获取并解析特定日期窗口的 RSS/Atom 订阅源 | | `POST` | `/api/analyze` | 代理至 Anthropic `/v1/messages` | | `GET` | `/api/config` | 加载所有已保存的配置 | | `PUT` | `/api/config` | 保存配置(始终排除 API key) | | `GET` | `/api/config/export` | 以 JSON 格式下载完整的配置及自定义订阅源 | | `POST` | `/api/config/import` | 从导出的 JSON 恢复配置 | | `GET` | `/api/feeds/custom` | 列出自定义订阅源 | | `POST` | `/api/feeds/custom` | 添加自定义订阅源 | | `DELETE` | `/api/feeds/custom/:id` | 移除自定义订阅源 | | `GET` | `/api/reports` | 列出所有报告(不含 body 字段) | | `GET` | `/api/reports/:id` | 获取包含 body 的单份报告 | | `POST` | `/api/reports` | 保存生成的报告 | | `DELETE` | `/api/reports/:id` | 删除报告 | | `GET` | `/api/costs` | 获取成本台账记录 | | `GET` | `/api/reports/:id/export?format=` | 导出报告 (md / html / pdf / docx) | ### `POST /api/fetch-feeds` 请求 body: ``` { "feeds": [ { "id": "talos", "name": "Cisco Talos", "xmlUrl": "https://blog.talosintelligence.com/feed", "url": "https://blog.talosintelligence.com" } ], "dateFrom": "2025-01-01", "dateTo": "2025-01-07" } ``` 响应: ``` { "articles": [ { "title": "Article title", "url": "https://...", "date": "2025-01-03", "summary": "First 800 chars of article text...", "feedName": "Cisco Talos", "feedIndex": 1 } ], "errors": [ { "feed": "Some Feed", "error": "Timeout" } ] } ``` 订阅源获取器行为: - 使用 `Promise.allSettled` 并行获取所有订阅源 - 每个订阅源有 8 秒的超时限制 (`AbortController`) - 在发送给 Claude 之前,每个订阅源最多限制 15 篇文章 - 不在日期窗口内的文章将被过滤掉 - 失败的订阅源(超时、HTTP 错误、解析错误)会出现在 `errors[]` 中,并在报告中予以注明 ## 导出格式 | 格式 | 引用 | 表格 | 备注 | |--------|-----------|--------|-------| | `.md` | `[N](url)` Markdown 超链接 | GFM 竖线表格 | 兼容 Obsidian、GitHub、Typora | | `.html` | `` 上标链接 | 带有深色 CSS 的 `` | 独立存在,深色主题与应用匹配 | | `.pdf` | `` 上标链接 | 带有深色 CSS 的 `
` | 打开打印对话框 — 在 Chrome 中启用“背景图形” | | `.docx` 蓝色上标 `[N]` 文本 | `` Word 表格 | 有效的基于 ZIP 的 DOCX,在 Word 和 LibreOffice 中打开均无错误 | 所有格式在导出前都会自动从存储的 `source_map` 重建参考文献部分,确保每个被引用的文章仅出现一次,且没有任何参考文献遗漏。 ## 支持的 Claude 模型 | 模型 | API ID | 输入 | 输出 | 最适用场景 | |-------|--------|-------|--------|---------| | Haiku 4.5 *(默认)* | `claude-haiku-4-5-20251001` | $1.00/1M | $5.00/1M | 日常简报,大任务量 | | Sonnet 4.5 | `claude-sonnet-4-5-20251101` | $3.00/1M | $15.00/1M | 质量与成本的平衡 | | Sonnet 4.6 | `claude-sonnet-4-6` | $3.00/1M | $15.00/1M | 最新功能 | | Opus 4.5 | `claude-opus-4-5` | $5.00/1M | $25.00/1M | 深度分析,复杂的报告 | ## 安全说明 - Anthropic API key **绝不写入磁盘或任何浏览器存储中**。它仅存在于 React 组件状态中,并在每次页面重新加载时清除。 - 后端会从所有配置保存 (`PUT /api/config`) 和配置导出 (`GET /api/config/export`) 中移除 `apiKey` 字段。 - 该服务器没有身份验证。它专为本地单用户使用而设计。请勿将端口 3001 暴露给网络。 - 所有订阅源获取操作均在服务端使用类似浏览器的 `User-Agent` 标头完成,以供研究使用。 ## 故障排除 **运行 `node server.js` 时出现 `Missing parameter name` 崩溃** 您安装了 Express 4。请运行 `npm install express@5` 进行升级。 **`Cannot find module 'node-fetch'`** 运行 `npm install node-fetch@2`。请注意 `@2` — v3 是不兼容的。 **`better-sqlite3` 构建失败** 安装 Xcode 命令行工具:`xcode-select --install`。在 Linux 上,请安装 `build-essential` 和 `python3`。 **数据库文件未创建 / 不可见** 数据库在与 `server.js` 相同的目录中创建。如果项目位于 iCloud Drive 内,iCloud 可能正在将该文件同步到云端。请将项目移至 `~/Library/Mobile Documents/` 之外的本地路径。 **在时间窗口内未找到文章** 大多数订阅源发布频率较低。请尝试扩大日期窗口(7 天或 14 天)。某些订阅源(NVD、OTX)需要身份验证或具有非标准的订阅源格式,可能返回零篇文章。请检查服务器终端 — 失败的订阅源会记录特定的错误。 **PDF 导出背景为白色** 在 Chrome 的打印对话框中,启用 **Background graphics**(更多设置 → Background graphics)。CSS 使用 `print-color-adjust: exact` 在 `html` 元素上设置深色背景,但除非勾选该选项,否则 Chrome 的打印对话框会覆盖它。 **DOCX 打开时出现“内容不可读”的警告** 此问题在当前版本中应已修复 — DOCX 现在是一个标准的 ZIP 归档。如果您仍然看到该警告,可能是您的 `server.js` 版本较旧。请确保您运行的是最新版本。
标签:AI分析, Claude, CVE检测, MITM代理, RSS聚合, 全栈应用, 威胁情报, 开发者工具, 自动化报告, 自定义脚本