## 概述
DepAnalyzer 解析依赖清单,通过生态系统的公共 registry 解析树中的每个包,并将每个包与 [OSV](https://osv.dev) 漏洞数据库的本地 PostgreSQL 缓存进行映射 —— 该数据库仅需注入一次,并通过每 5 分钟的增量同步保持最新。缺失的 CVSS 分数会从 [NVD](https://nvd.nist.gov) 进行补充。结果被汇总为风险评分,按包进行分组,并在带有实时依赖关系图的交互式 UI 中呈现。
本地 CVE 缓存(涵盖 npm、PyPI 和 Maven 的超过 24.9 万个漏洞)意味着扫描查询只需几毫秒而不是几秒钟 —— 无需为每个包进行实时的 API 往返请求。
**扫描工作流:**
1. 解析上传的清单(提取包名称和锁定的版本)
2. 通过公共 registry API 解析完整的依赖树,最深可达三层
3. 查询本地 PostgreSQL CVE 缓存(DB 优先);缓存未命中时回退到实时 OSV API
4. 必要时从 NVD 补充缺失的 CVSS 分数
5. 构建一个带有唯一事务 ID 的不可变、带版本的快照
6. 在渲染之前在前端验证快照契约
7. 显示风险评分、CVE 列表、依赖关系图以及针对各个生态系统的修复命令
专为希望洞察其供应链而又不想承担企业级工具开销的开发者而构建。
## 功能特性
### 依赖扫描
- 解析 `package.json`、`package-lock.json`、`requirements.txt` 和 `pom.xml`
- 解析直达和传递依赖,最深可达三层
- 根据文件名**以及粘贴的内容**自动检测生态系统(JSON → npm,XML → Maven,`pkg==ver` → PyPI)
- PostgreSQL 解析器缓存 —— 重复的包查询将完全跳过 registry API(热缓存:约 5ms 对比 约 500ms)
- 处理 npm 的 `dependencies`、`devDependencies` 和 `peerDependencies`
- 使用 OSV(主要漏洞源)无需 API key
### 漏洞分析
- 双源查询:OSV(主源)+ NVD(CVSS 补充)
- 带有严重性标签的 CVSS v3.1 / v3.0 / v2 评分
- **EPSS 评分** — CVE 在 30 天内在野外被利用的概率(0–100%),数据来源于 Cyentia Institute 并每天同步
- **CISA KEV 标志** — 标记已在[已知被利用漏洞](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)列表中确认的 CVE;这些漏洞将以醒目的警告显示,并在详细信息面板中自动选中
- 漏洞去重并按 `package@version` 分组
- CVE 路径跟踪 —— 显示每个漏洞是如何进入依赖树的
- 提供已发布的修复版本建议
### 风险评分
- 综合评分 (0–100),使用跨越四个严重性等级的对数衰减模型
- 标签:安全、低危、中危、高危、严重
- 优先修复计数优先显示严重和高危漏洞
- 加载时自动选择最紧急的 CVE —— KEV 确认的漏洞优先级高于单纯的严重性等级
### 依赖图
- 无需外部图形库构建的交互式 SVG 图表
- 缩放(Ctrl+滚动)和平移(拖拽)
- 按严重性过滤或切换视图模式(全部 / 有漏洞 / 孤立)
- 直达和传递节点带有漏洞指示器进行渲染
### 导出与报告
- 通过 ReportLab 生成 PDF 报告:项目元数据、风险评分、包含修复版本的完整漏洞表
- 导出 CSV 以便进行电子表格分析
- 特定生态系统的批量修复命令(`npm install`、`pip install -r`、`mvn clean install`)
### 扫描历史
- 基于浏览器 localStorage 的历史记录,按项目名称分组
- 每个项目最多存储 20 次扫描,带有时间戳和摘要快照
### 知识库
- 八个学习板块:SCA、依赖类型、CVSS、CVE、供应链风险、修复、CI/CD 集成、SBOM
- 包含 25 多个通俗易懂术语定义的词汇表,通过内联工具提示展示
### 系统状态栏
- 导航栏下方的实时运行状态条 —— 在所有非首页可见
- 第一行:`SYS · DB · OSV · NVD` 状态点 + 运行时间 + UTC 时钟 + 版本
- 第二行:`SYS_READY · TXN · DB · OSV · NVD_POLL` — 会话事务 ID 和同步状态
- 可切换的 `SYSTEM_LOGS` 面板 —— 来自健康数据的实时日志条目 + 实时活动(心跳、速率限制重置、缓存刷新)
- 所有状态字段均连接到真实的 `/api/health` 数据 —— 没有虚假指标
### 主题系统
- 通过顶部控件切换深色和浅色主题,并持久化到 localStorage
- 全面采用 CSS 自定义属性 —— UI 中没有任何硬编码的颜色
- 在两种主题中,严重性指标的对比度均符合 WCAG AA 标准
### 响应式设计
- 移动端汉堡菜单导航
- 针对移动端和桌面端视图下的文件上传和结果提供自适应布局
- 跨浏览器 E2E 覆盖:Chromium、Firefox 和 WebKit
### GitHub Action — 每次提交时自动扫描
- 在任何项目中安装 `sky2194/dependency-analyzer@v1`,即可在每次 push 和 pull request 时扫描依赖项
- 向 PR 发布完整的报告评论 —— 风险评分、CVE 详细分类,以及指向应用程序中可视化报告的深层链接
- **CISA KEV 警报** — 如果扫描中发现任何 CVE 位于 CISA 已知被利用漏洞列表中,PR 评论顶部将会出现一个醒目的警告区块
- 为 GitHub Actions 汇总面板和 PR 检查选项卡中可见的 KEV CVE 发出 `::warning::` 注解
- 绝不阻塞或拒绝 PR —— 默认仅作为信息参考
- 将 `risk-score`、`scan-url`、`critical`、`high` 和 `kev-count` 作为步骤输出公开,供后续工作流步骤使用(Slack 警报、Jira ticket 等)
- 扫描结果会在服务器端保留 30 天 —— “查看完整报告”链接将打开包含依赖关系图、CVE 路径和修复命令的完整应用
## 支持的生态系统
| 生态系统 | 清单文件 | Registry | 仲裁规则 |
|-----------|---------------|----------|----------------|
| npm / Node.js | `package.json`, `package-lock.json` | registry.npmjs.org | 就近深度优先 |
| PyPI / Python | `requirements.txt` | pypi.org/pypi | 首个匹配版本 |
| Maven / Java | `pom.xml` | search.maven.org | 首个声明优先 |
## 技术栈
**后端**
| 包 | 版本 | 作用 |
|---------|---------|------|
| Flask | 3.0.0 | HTTP 框架 |
| Gunicorn | 21.2.0 | WSGI 服务器 |
| Flask-CORS | 4.0.0 | CORS 中间件 |
| psycopg2-binary | 2.9.9 | PostgreSQL 驱动 |
| APScheduler | 3.10.4 | 后台同步调度器 |
| ReportLab | 4.2.5 | PDF 生成 |
| requests | 2.31.0 | 外部 API 调用 |
| xmltodict | 0.13.0 | pom.xml 解析 |
| packaging | 23.2 | 版本比较 |
**前端**
| 包 | 版本 | 作用 |
|---------|---------|------|
| React | 18.2.0 | UI 框架 |
| Vite | 5.1.0 | 构建工具和开发服务器 |
| React Router DOM | 6.22.0 | 客户端路由 |
| Axios | 1.6.0 | HTTP 客户端 |
字体:Syne(标题)、DM Sans(正文)、DM Mono(代码) — 通过 Google Fonts 加载。
**测试**
## 运行测试
### E2E 测试
```
cd frontend
npm run test:e2e # headless
npm run test:e2e:headed # with browser visible
npm run test:e2e:ui # interactive UI mode
```
测试涵盖 5 个领域(共 41 个测试):
- **首页** — hero 区、CTA、导航链接、移动端汉堡菜单
- **扫描器** — 选项卡、示例加载、自动检测、键盘可访问性
- **结果** — 完整扫描流程、CVE 表格、过滤器、图表、导出、崩溃保护
- **历史** — 加载、空状态、无崩溃删除
- **知识库** — 所有板块、移动端选择器
### CI 门禁 (内部)
发往 `main` 的每个 PR 都会通过 GitHub Actions 自动运行完整的 Playwright + pytest 测试套件。
如果有任何测试失败,则无法合并 PR。
失败产物(屏幕截图、视频)将被上传以供调试。
### 在您自己的 CI 流水线中使用 DepAnalyzer
在任何项目的 `.github/workflows/security.yml` 中添加以下内容,即可在每次 push 和 PR 时获得自动的依赖扫描:
```
name: Dependency Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: sky2194/dependency-analyzer@v1
```
无需配置 —— 该 Action 会从工作区自动检测您的清单(`package.json`、`requirements.txt` 或 `pom.xml`)。只有在路径不标准时才需进行覆盖:
```
- uses: sky2194/dependency-analyzer@v1
with:
manifest-file: path/to/requirements.txt
```
该 Action 会扫描您的依赖项,发布包含完整报告的 PR 评论(如果发现任何被活跃利用的 CVE,将包含 CISA KEV 警报),并直接链接到应用程序中的可视化报告。它绝不会导致构建失败。
### 后端测试
```
cd backend
pytest
pytest --coverage
```
| 工具 | 版本 | 作用 |
|------|---------|------|
| Playwright | 1.60.0 | E2E 和响应式测试 |
| pytest | 8.1.0 | 后端单元和集成测试 |
## 架构
```
User uploads manifest
│
▼
┌──────────────────────────────────────────┐
│ Flask backend (app.py) │
│ │
│ 1. Parse │
│ npm_parser / pypi_parser / │
│ maven_parser / lockfile_parser │
│ │
│ 2. Resolve (registry API calls) │
│ npm_resolver / pypi_resolver / │
│ maven_resolver / lockfile_resolver │
│ LRU cache (500 entries, 1h TTL) │
│ Circuit breaker + retry-backoff │
│ │
│ 3. Scan (cve/scanner.py) │
│ BFS traversal, up to 8 OSV workers │
│ DB-first lookup (PostgreSQL cache) │
│ → live OSV fallback on cache miss │
│ → NVD CVSS enrichment │
│ → EPSS score + KEV flag enrichment │
│ LRU cache (1000 entries, 1h TTL) │
│ │
│ 4. Build snapshot │
│ transaction_id (UUID v4) │
│ snapshot_version: 1 │
│ status: COMPLETED │
│ summary, vulnerabilities, graph │
└──────────────────┬───────────────────────┘
│ JSON response
▼
┌──────────────────────────────────────────┐
│ React frontend │
│ │
│ validateSnapshot.js │
│ Hard contract validation │
│ Throws on ANY schema violation │
│ No silent fallbacks or partial renders│
│ │
│ Analytics.jsx — results and CVE list │
│ DependencyGraph.jsx — SVG graph │
│ projectStore.js — localStorage history │
└──────────────────────────────────────────┘
```
### 事务模型
每次扫描响应都包含一个 `transaction_id` (UUID v4) 和 `snapshot_version: 1`。前端在渲染前会验证完整的快照结构 —— 任何缺失的字段、错误的类型或 schema 版本不匹配都会立即抛出错误。如果在之前的扫描完成之前开始了新的扫描,则之前的过期事务将被拒绝。
### 快照契约
```
{
transaction_id: uuid-v4 string,
snapshot_version: 1,
status: "COMPLETED",
ecosystem: "npm" | "pypi" | "maven",
project_name: string,
summary: {
risk_score: number, // 0–100
risk_label: string, // Secure | Low | Medium | High | Critical
total_packages: number,
direct_dependencies: number,
transitive_dependencies: number,
vulnerabilities: number,
critical: number,
high: number,
medium: number,
low: number,
secure_package_count: number,
vulnerable_package_count: number,
vulnerable_direct_count: number,
vulnerable_transitive_count: number,
priority_fix_count: number
},
grouped_packages: [...],
vulnerabilities: [...],
graph: {...},
dependency_tree: {...},
scan_timestamp: unix timestamp
}
```
### 风险评分算法
对数衰减可防止任何单一严重性等级饱和评分:
```
score = 40 × (1 − e^(−critical/3))
+ 30 × (1 − e^(−high/5))
+ 20 × (1 − e^(−medium/8))
+ 10 × (1 − e^(−low/10))
Final = min(100, round(score))
```
| 分数 | 标签 |
|-------|-------|
| 0 | 安全 |
| 1–39 | 低危 |
| 40–69 | 中危 |
| 70–89 | 高危 |
| 90–100 | 严重 |
## 入门指南
### 前置条件
- Python 3.9+
- Node.js 18+
- npm 9+
### 快速开始
```
git clone https://github.com/sky2194/dependency-analyzer.git
cd dependency-analyzer
chmod +x start.sh
./start.sh start
```
该脚本会创建 Python 虚拟环境,安装所有依赖项,并启动这两个服务。
```
Backend → http://localhost:5000
Frontend → http://localhost:3000
```
### 启动脚本命令
```
./start.sh start # Start both services
./start.sh stop # Stop both services
./start.sh restart # Restart both services
./start.sh logs # Tail backend + frontend logs
```
### 手动设置
**后端:**
```
cd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python app.py
```
**前端(在单独的终端中):**
```
cd frontend
npm install
npm run dev
```
### 环境变量
**后端 (`backend/.env`):**
| 变量 | 必需 | 描述 |
|----------|----------|-------------|
| `DATABASE_URL` | 是(生产环境) | PostgreSQL 连接字符串。格式:`postgresql://user:pass@host/db?sslmode=require`。免费套餐:[neon.tech](https://neon.tech) |
| `NVD_API_KEY` | 否 | NVD API key。没有它:5 次请求/30秒。有它:50 次请求/30秒。在 nvd.nist.gov/developers/request-an-api-key 获取 |
| `ALLOWED_ORIGINS` | 否 | 逗号分隔的 CORS 源。在开发中默认为宽松模式。 |
| `ALLOW_VERCEL_PREVIEWS` | 否 | 设置为 `true` 以允许 `*.vercel.app` 预览 URL。 |
| `USE_REDIS_RATE_LIMIT` | 否 | 设置为 `true` 可从内存限制切换到基于 Redis 的速率限制。 |
| `DISABLE_SCHEDULER` | 否 | 设置为 `true` 以禁用后台 OSV/EPSS/KEV 同步(在开发中很有用)。 |
| `INTERNAL_TOKEN` | 否 | 用于 `/api/health` 完整响应密钥 token。公共调用者将获得最简响应。在前端设置与 `VITE_INTERNAL_TOKEN` 相同的值。使用 `openssl rand -hex 32` 生成。 |
```
cp backend/.env.example backend/.env
# 编辑 backend/.env 为你的值
```
**前端 (`frontend/.env`):**
| 变量 | 必需 | 描述 |
|----------|----------|-------------|
| `VITE_API_URL` | 仅生产环境 | 后端基础 URL。在开发环境中,Vite 会自动将 `/api/*` 代理到 `localhost:5000`。 |
| `VITE_INTERNAL_TOKEN` | 否 | 与后端的 `INTERNAL_TOKEN` 相匹配。允许前端接收完整的 `/api/health` 响应。 |
## 数据库设置 (PostgreSQL CVE 缓存)
DepAnalyzer 使用本地 PostgreSQL 缓存来实现快速 CVE 查询。如果没有它,扫描将回退到实时的 OSV API 调用(速度较慢,但可以运行)。
### 1. 创建免费的 Neon 数据库
1. 在 [neon.tech](https://neon.tech) 注册(免费,无需信用卡)
2. 创建项目 → 命名为 `depanalyzer`,区域选择 US East
3. 复制连接字符串:
postgresql://user:password@ep-xxx.neon.tech/depanalyzer?sslmode=require
4. 将其添加到 `backend/.env` 中:
DATABASE_URL=postgresql://user:password@ep-xxx.neon.tech/depanalyzer?sslmode=require
### 2. 下载 OSV 数据(一次)
```
curl -L -o /tmp/npm.zip https://osv-vulnerabilities.storage.googleapis.com/npm/all.zip
curl -L -o /tmp/pypi.zip https://osv-vulnerabilities.storage.googleapis.com/PyPI/all.zip
curl -L -o /tmp/maven.zip https://osv-vulnerabilities.storage.googleapis.com/Maven/all.zip
```
### 3. 注入数据库(一次,约 5-10 分钟)
```
cd backend
python3 sync/seed.py
```
这将加载 24.9 万+ 个漏洞 + EPSS 评分 + CISA KEV 条目。只需运行一次 —— 增量同步会自动保持最新。
### 4. 完成了
后端会在每次重启时初始化 schema 并启动增量同步调度器。OSV 数据每 5 分钟刷新一次(仅限增量 —— 不是完全重新下载)。
## 用法
1. 打开 `http://localhost:3000`
2. 选择一个生态系统选项卡 (npm、PyPI 或 Maven)
3. 上传您的清单文件或直接粘贴其内容
4. 点击 **扫描并检测漏洞 (Scan & Detect Vulnerabilities)**
5. 查看风险评分、CVE 列表、依赖关系图和修复命令
6. 如果需要,导出为 PDF 或 CSV
7. 结果会自动保存到扫描历史中
## 项目结构
```
dependency-analyzer/
├── start.sh # Orchestration script (start/stop/restart/logs)
├── LICENSE # AGPL v3
│
├── frontend/
│ ├── package.json
│ ├── vite.config.js # Dev server on :3000, proxy /api/* → :5000
│ ├── vercel.json # Vercel deployment config
│ ├── .env.example
│ ├── index.html
│ └── src/
│ ├── App.jsx # Root layout, routing, theme toggle, ScanContext
│ ├── index.css # CSS custom properties, themes, animations
│ ├── pages/
│ │ ├── Landing.jsx # Home page with hero and feature showcase
│ │ ├── Dashboard.jsx # Scanner interface with file upload
│ │ ├── Scanning.jsx # Loading state during active scan
│ │ ├── Analytics.jsx # Results page (risk score, CVE list, graph)
│ │ ├── History.jsx # Scan history browser
│ │ └── Learn.jsx # Knowledge base
│ ├── components/
│ │ ├── DependencyGraph.jsx # SVG interactive dependency graph
│ │ ├── FileUpload.jsx # Upload, paste textarea, ecosystem selector
│ │ ├── ErrorBoundary.jsx # React error boundary
│ │ ├── StepBanner.jsx # Step progress indicator
│ │ └── Tooltip.jsx # Glossary tooltips
│ ├── utils/
│ │ ├── config.js # API base URL
│ │ ├── projectStore.js # localStorage scan history (max 20/project)
│ │ ├── fixAll.js # Ecosystem-specific batch fix commands
│ │ ├── validateSnapshot.js # Hard contract validation (throws on violation)
│ │ └── normalizeSnapshot.js
│ └── data/
│ ├── ecosystems.js # Ecosystem definitions and filename detection
│ └── terms.js # Glossary (25+ terms)
│
├── backend/
│ ├── app.py # Flask application, routes, CORS, rate limiter
│ ├── requirements.txt
│ ├── .env.example
│ ├── parsers/
│ │ ├── npm_parser.py # package.json parser
│ │ ├── pypi_parser.py # requirements.txt parser
│ │ ├── maven_parser.py # pom.xml parser
│ │ └── lockfile_parser.py # package-lock.json parser
│ ├── resolvers/
│ │ ├── npm_resolver.py # npm registry resolution
│ │ ├── pypi_resolver.py # PyPI registry resolution
│ │ ├── maven_resolver.py # Maven Central resolution
│ │ └── lockfile_resolver.py # Lock file resolution (no registry calls)
│ ├── cve/
│ │ ├── scanner.py # BFS scan orchestration — DB-first with OSV fallback
│ │ ├── db_scanner.py # PostgreSQL CVE lookup (version-aware)
│ │ ├── osv_client.py # OSV API client with circuit breaker (fallback)
│ │ └── nvd_client.py # NVD API client (CVSS enrichment)
│ ├── sync/
│ │ ├── osv_sync.py # Delta sync via OSV API every 5 minutes
│ │ ├── epss_kev_sync.py # EPSS scores + CISA KEV list (daily)
│ │ └── seed.py # One-time seed from local OSV ZIP dumps
│ ├── db.py # PostgreSQL connection manager + schema
│ ├── exports/
│ │ ├── pdf_export.py # ReportLab PDF generation
│ │ └── csv_export.py # CSV export
│ ├── utils/
│ │ ├── validation.py # Input sanitization (XSS, injection prevention)
│ │ └── circuit_breaker.py # Three-state circuit breaker
│ └── tests/
│ ├── test_api.py
│ ├── test_parsers.py
│ ├── test_resolvers.py
│ ├── test_dependency_graph.py
│ ├── test_vulnerability_system.py
│ └── test_cve.py
│
└── tests/ # Playwright E2E tests
├── package.json
├── playwright.config.ts # Chromium, Firefox, WebKit; auto-starts Vite
├── utils/
│ ├── apiHelpers.ts # Mock payloads, scan helpers
│ ├── transactionValidator.ts # Transaction ID assertions
│ ├── graphAssertions.ts # Dependency graph validation
│ ├── layoutAssertions.ts # Responsive layout assertions
│ ├── overflowAssertions.ts # Overflow/scroll behavior
│ ├── themeAssertions.ts # Dark/light theme validation
│ ├── viewportHelpers.ts # Mobile/desktop viewport simulation
│ └── mockNetwork.ts # Network interception for failure tests
├── 01_user_journey.spec.ts
├── 02_concurrent_scans.spec.ts
├── 03_network_failure.spec.ts
├── 04_backend_contract_drift.spec.ts
├── 05_transaction_race.spec.ts
├── 06_render_stability.spec.ts
├── 07_data_integrity.spec.ts
└── responsive/
├── 09_scan_flow_responsive.spec.ts
└── 10_cross_ecosystem_layout.spec.ts
```
## API 参考
| 方法 | Endpoint | 描述 |
|--------|----------|-------------|
| `POST` | `/api/scan` | 解析并扫描依赖清单 |
| `POST` | `/api/scan-package` | 根据名称和版本扫描单个包 |
| `GET` | `/api/scans/
` | 通过事务 ID 检索存储的扫描快照(由 GitHub Action 的可共享链接使用) |
| `GET` | `/api/cve/` | 获取特定 CVE 的详细信息 |
| `POST` | `/api/export/pdf` | 从扫描快照生成 PDF 报告 |
| `POST` | `/api/export/csv` | 生成漏洞的 CSV 导出 |
| `GET` | `/api/health` | 健康检查 — 返回状态、DB 连接状态以及最后 OSV/EPSS/KEV 同步时间戳 |
### POST `/api/scan`
**请求体:**
```
{
"content": "",
"filename": "package.json",
"ecosystem": "npm"
}
```
`ecosystem` 是可选的 — 如果省略,则从 `filename` 自动检测。请求体大小上限为 512KB。
**响应:** 与上述契约匹配的完整快照对象。
### POST `/api/scan-package`
**请求体:**
```
{
"package": "lodash",
"version": "4.17.20",
"ecosystem": "npm"
}
```
解析最深为 2 层的传递依赖,并扫描整个树。
## 运行测试
**后端:**
```
cd backend
source venv/bin/activate
pytest tests/ -v
```
**E2E —— 请先确保后端正在运行:**
```
cd tests
npm install
npx playwright install
npx playwright test # all specs, all browsers
npx playwright test 01_user_journey # single spec
npx playwright test --project=chromium # single browser
npx playwright test responsive/ # responsive specs only
npx playwright show-report # open HTML report
```
**前端单元测试:**
```
cd frontend
npm test # run once
npm run test:watch # watch mode
npm run test:coverage # with coverage
```
### E2E 测试套件
| Spec | 覆盖范围 |
|------|---------------|
| `01_user_journey` | 完整扫描工作流、页面导航、多扫描排序 |
| `02_concurrent_scans` | 竞争条件、事务隔离 |
| `03_network_failure` | 超时处理、网络弹性 |
| `04_backend_contract_drift` | 快照版本强制执行、硬契约验证 |
| `05_transaction_race` | 过期响应阻塞、并发扫描处理 |
| `06_render_stability` | 组件渲染一致性、数据绑定 |
| `07_data_integrity` | 漏洞去重、包计数、图表验证 |
| `09_scan_flow_responsive` | 移动端视口、文件上传交互 |
| `10_cross_ecosystem_layout` | 不同屏幕尺寸下的 npm / PyPI / Maven 表单布局 |
## 安全模型
### 输入验证
在进行任何 registry API 调用之前,所有的包名称、版本和 Maven 坐标都会通过正则表达式进行验证:
- 包名称:`^[@a-zA-Z0-9._\-\/]+$` (阻止 XSS 和路径遍历)
- 版本:带操作符的 semver、`*`、`x`、`latest`
- Maven groupId / artifactId:`^[a-zA-Z0-9._\-]+$` (阻止 XML 注入)
- 清单请求体:上限为 512KB
### 速率限制
- 每个客户端 IP 每 60 秒窗口内 20 次请求 — 应用于包括 `/api/cve` 在内的所有 endpoint
- 默认在内存中进行;使用 `USE_REDIS_RATE_LIMIT=true` 切换到 Redis
- 默认情况下,`/api/health` 返回最简的公共响应;完整详细信息需要 `X-Internal-Token` 请求头
### 弹性
- **断路器** — OSV 和 NVD 客户端各自使用一个三态断路器(连续 5 次失败后从 CLOSED → OPEN → 30 秒恢复后变为 HALF_OPEN)。防止在上游 API 性能下降时出现级联故障。
- **带退避的重试** — 解析器 registry 调用使用指数退避(基准 0.5 秒,最大 3 秒,每次调用最多重试 1 次)。
### 安全标头
每个后端响应都包含:
```
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
```
### 前端契约执行
`validateSnapshot.js` 会在 UI 渲染之前验证每个扫描响应。任何缺失的字段、错误的类型或意外的 schema 版本都会立即抛出错误 —— 不存在部分渲染或静默的数据强制转换。
## 性能与稳定性
- **扫描并发** — 每次扫描最多并行运行 8 个 OSV worker 和 6 个 NVD worker。
- **LRU 缓存** — 解析器结果缓存 1 小时(500 个条目);CVE 结果缓存 1 小时(1000 个条目)。对相同包的重复扫描避免了冗余的 registry 和 OSV 调用。
- **事务隔离** — 每次扫描都带有一个 UUID 事务 ID。前端会拒绝任何 ID 与当前活动扫描不匹配的响应,从而防止在之前的扫描完成之前开始新扫描时出现过期结果。
- **硬契约验证** — `validateSnapshot.js` 在出现任何 schema 违规时抛出错误。对于畸形数据,不存在回退值、默认填充字段或部分渲染。
## 已知局限
- **可达性** — CVE 的标记是基于包版本,而不是基于易受攻击的代码路径在您的应用程序中是否可达。
- **传递深度** — 对 npm 最多解析三层,对 PyPI 和 Maven 最多解析两层。非常深的树不会被完全遍历。
- **速率限制** — 内存中的速率限制会在服务器重启时重置。使用 Redis (`USE_REDIS_RATE_LIMIT=true`) 可在重启后保持持续的执行。
- **无身份验证** — 该应用程序是无状态的。扫描历史记录仅存储在浏览器的 localStorage 中。
- **DB 版本覆盖范围** — OSV 种子数据捕获 OSV dump 文件中列出的版本。仅具有基于范围的影响条目(无明确版本列表)的包默认为保守匹配(假定为受影响)。实时的 OSV 回退机制可以精确解决这些问题。
## 截图
**首页**

**扫描器 — 带有实时示例加载器的 npm、PyPI、Maven 选项卡**

**扫描结果 — npm (lodash 4.17.11, axios 0.21.1 · 风险 68/100 · 73 个 CVE)**

**扫描结果 — Maven (log4j 1.2.17, commons-collections 3.2.1 · 风险 46/100 · 8 个 CVE · EPSS 71%)**

**扫描结果 — PyPI (Django 3.2, requests 2.27, Pillow 9.0 · 风险 24/100 · 9 个 CVE)**

**依赖关系图 — 带有严重性过滤的交互式 SVG**

## 部署
### 前端
```
cd frontend
npm run build # outputs to /dist
```
在 Vercel 环境设置中将 `VITE_API_URL` 设置为后端 URL。`vercel.json` 会将 `/api/*` 重写到后端主机。
### 后端
```
cd backend
source venv/bin/activate
gunicorn app:app --bind 0.0.0.0:5000 --workers 2
```
将 `ALLOWED_ORIGINS` 设置为您的前端域名,将 `DATABASE_URL` 设置为您的 Neon 连接字符串,并可选择设置 `NVD_API_KEY` 以获得更好的 NVD 速率限制。
**不要在服务器上的文件中设置 `DATABASE_URL`。** 请将其作为环境变量设置在您的主机平台仪表板中(DigitalOcean → App → Environment Variables,或者 Render/Railway 设置中)。这可以让您的数据库密码远离文件系统。
### 自动部署 hook(可选)
在服务器上设置一个 `post-merge` hook,以便 `git pull` 时自动重启服务:
```
cat > /var/www/dependency-analyzer/.git/hooks/post-merge << 'EOF'
#!/bin/bash
cd /var/www/dependency-analyzer
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" != "main" ]; then exit 0; fi
eval $(grep -E "^Environment=" /etc/systemd/system/dependency-analyzer.service.d/override.conf | sed 's/Environment=//;s/"//g' | xargs -I{} echo export {})
if git diff HEAD@{1} HEAD --name-only | grep -q "requirements.txt"; then
source backend/venv/bin/activate && pip install -r backend/requirements.txt -q
fi
if git diff HEAD@{1} HEAD --name-only | grep -q "backend/db.py"; then
backend/venv/bin/python3 -c "from db import init_schema; init_schema()"
fi
systemctl restart dependency-analyzer
echo "✅ Deploy complete"
EOF
chmod +x /var/www/dependency-analyzer/.git/hooks/post-merge
```
之后,部署仅需一条命令:
```
ssh root@your-server "cd /var/www/dependency-analyzer && git pull origin main"
```
## 故障排除
**端口已被占用:**
```
./start.sh restart
```
**后端无法启动:**
```
./start.sh logs # check backend log output
rm -rf backend/venv # recreate virtual environment if corrupt
./start.sh start
```
**前端无法启动:**
```
./start.sh logs
rm -rf frontend/node_modules
./start.sh start
```
## 贡献
1. Fork 本仓库并从 `main` 创建一个分支。
2. 对于后端更改,请在 `backend/tests/` 中添加或更新测试。
3. 对于前端更改,请验证其在深色和浅色主题下以及在移动端和桌面端视口中的行为。
4. 在发起 pull request 之前运行 Playwright 测试套件。
5. 保持 `validateSnapshot.js` 和 `app.py` 中的快照契约同步 —— 后端响应中添加的任何字段都必须反映在前端验证中。
## 许可证
**GNU Affero General Public License v3.0 (AGPL v3)** — 详情请参阅 [LICENSE](LICENSE)。
版权所有 2026 Sai Koutilya Yerabati。
DepAnalyzer 可免费使用、修改和自托管。如果您将修改后的版本作为网络服务 运行,则必须根据 AGPL v3 开源您的代码。有关商业许可的咨询,请[开启一个 issue](https://github.com/sky2194/dependency-analyzer/issues)。