# 安全扫描指南

本项目集成了多层安全扫描,覆盖依赖审计、深度依赖分析、静态分析、容器镜像扫描与动态应用安全测试(DAST)。

## 一、CI 中的安全扫描流程

### 1.1 主 CI 流水线(`.gitea/workflows/ci.yml`)

主流水线在 `push`/`pull_request` 到 `main` 时触发,包含三个 Job:

| Job | 触发条件 | 说明 |
|-----|---------|------|
| `build-deploy` | push/PR to main | 构建、测试、部署到 Docker |
| `security-scan` | push/PR to main(依赖 build-deploy) | 完整安全扫描,失败不阻塞构建 |
| `scheduled-backup` | schedule cron `0 2 * * *` | 每天凌晨 2 点数据库备份 |

`security-scan` Job 依次执行以下扫描,所有步骤均设置 `continue-on-error: true`,**扫描失败不阻塞构建**,但会生成报告并上传为 artifact(`security-reports`):

1. **npm audit** — 依赖漏洞审计(moderate 级别),生成 `audit-report.json`
2. **Snyk 扫描** — 深度依赖分析(`--severity-threshold=high`),生成 `snyk.sarif`,需配置 `SNYK_TOKEN` secret
3. **Trivy 文件系统扫描** — 扫描项目代码与依赖,生成 `trivy-fs-report.json` 与表格视图
4. **OWASP ZAP 基线扫描** — 对部署后的应用执行 DAST,目标为 `NEXTAUTH_URL` secret 或 `http://localhost:8015`

### 1.2 独立安全工作流(`.gitea/workflows/security.yml`)

独立工作流执行**深度安全扫描**,触发方式:

- **定时**:每周一凌晨 3 点(`cron: "0 3 * * 1"`)
- **手动**:`workflow_dispatch`,可指定 `target_url`(DAST 目标)与 `skip_dast` 选项

执行内容:

| 步骤 | 工具 | 类型 | 输出 |
|------|------|------|------|
| 依赖扫描 | npm audit | 依赖 | `audit-report.json` |
| 深度依赖 + 静态分析 | Snyk(`--severity-threshold=medium`) | 依赖 + 代码 | `snyk.sarif` |
| 文件系统扫描 | Trivy fs | 代码 + 依赖 | `trivy-fs-report.json` |
| 容器镜像扫描 | Trivy image | 容器 | `trivy-image-report.json` |
| DAST | OWASP ZAP baseline | 动态 | 控制台报告 |
| 汇总报告 | shell + jq | 汇总 | `security-summary.md` |

所有报告上传为 artifact `security-reports-full`。

## 二、各扫描工具的作用

| 工具 | 作用 | 覆盖范围 |
|------|------|---------|
| **npm audit** | Node.js 依赖漏洞审计,基于 npm advisory 数据库 | 直接与间接 npm 依赖 |
| **Snyk** | 深度依赖分析 + 代码静态分析,漏洞库更广,含许可证检查 | npm 依赖 + 源码 |
| **Trivy(fs)** | 文件系统扫描,检测依赖锁文件、IaC 配置、密钥泄露 | 项目代码、配置、密钥 |
| **Trivy(image)** | 容器镜像扫描,检测镜像层漏洞与配置问题 | 构建出的 Docker 镜像 |
| **OWASP ZAP** | 动态应用安全测试(DAST),模拟攻击发现运行时漏洞 | 运行中的 Web 应用 |

## 三、如何处理扫描发现的漏洞

### 3.1 处理流程

1. **查看报告**:从 CI artifact 下载 `security-reports` / `security-reports-full`
2. **分级评估**:按漏洞等级确定处理优先级(见分级标准)
3. **修复或缓解**:
   - 升级受影响依赖到修复版本
   - 若无法立即升级,评估是否可接受并记录抑制项
   - 对运行时漏洞,通过 WAF/配置/代码修复
4. **验证**:本地运行 `npm run security:scan` 验证修复效果
5. **记录**:更新抑制配置文件,记录处理决策

### 3.2 抑制配置文件

对于经评估确认可接受的漏洞,通过以下文件抑制:

- **`.gitea/suppressions.json`** — Snyk 漏洞抑制,每条需填写 `id`、`package`、`severity`、`reason`、`expires`(到期时间)、`owner`
- **`.trivyignore`** — Trivy 忽略的 CVE 列表,每行一个 CVE ID,带注释说明原因

> 抑制项到期后必须重新评估。`suppressions.json` 中 `policy.reviewCadenceDays: 30` 要求每 30 天复审一次。

### 3.3 必需的 Secrets

| Secret | 用途 | 必需性 |
|--------|------|--------|
| `SNYK_TOKEN` | Snyk API 令牌 | 推荐(无则 Snyk 步骤跳过) |
| `NEXTAUTH_URL` | ZAP DAST 扫描目标 URL | 可选(默认 localhost:8015) |

## 四、本地扫描方法

### 4.1 npm 脚本

```bash
# 仅依赖审计
npm run security:audit

# 完整本地扫描(npm audit + Trivy fs)
npm run security:scan
```

### 4.2 直接运行脚本

**Linux/macOS:**
```bash
chmod +x scripts/security-scan.sh
./scripts/security-scan.sh
```

**Windows PowerShell:**
```powershell
.\scripts\security-scan.ps1
```

### 4.3 退出码

| 退出码 | 含义 |
|--------|------|
| `0` | 无高危(critical/high)漏洞 |
| `1` | 存在高危漏洞,需尽快处理 |

### 4.4 前置依赖

- **Node.js + npm** — 必需
- **Trivy** — 可选(未安装则跳过文件系统扫描),[安装指南](https://aquasecurity.github.io/trivy/latest/getting-started/installation/)
- **jq**(仅 bash 脚本)— 可选(未安装则显示原始报告)

## 五、漏洞分级标准

| 等级 | 说明 | 示例 |
|------|------|------|
| **Critical** | 可被远程利用,导致 RCE、认证绕过、数据完全泄露 | 远程代码执行、SQL 注入 |
| **High** | 可导致权限提升、敏感数据泄露、服务中断 | XSS、认证缺陷、SSRF |
| **Medium** | 需特定条件触发,影响有限 | 信息泄露、CSRF |
| **Low** | 影响极小,通常为信息收集类 | 版本号泄露、低危 ReDoS |

## 六、修复 SLA(服务等级协议)

| 漏洞等级 | 修复时限 | 处理要求 |
|---------|---------|---------|
| Critical | 24 小时 | 立即修复或下线受影响服务,发布紧急补丁 |
| High | 7 天 | 优先排期修复,升级依赖或应用补丁 |
| Medium | 30 天 | 纳入迭代计划修复 |
| Low | 90 天 | 评估后决定修复或抑制 |

> 超过 SLA 未处理的漏洞需升级至安全负责人,并在 `suppressions.json` 中记录延期原因。

## 七、相关文件清单

| 文件 | 用途 |
|------|------|
| `.gitea/workflows/ci.yml` | 主 CI 流水线(含 security-scan job) |
| `.gitea/workflows/security.yml` | 独立深度安全扫描工作流 |
| `.gitea/suppressions.json` | Snyk 漏洞抑制配置 |
| `.trivyignore` | Trivy CVE 忽略列表 |
| `scripts/security-scan.sh` | 本地扫描脚本(Linux/macOS) |
| `scripts/security-scan.ps1` | 本地扫描脚本(Windows) |
| `scripts/audit.sh` | 依赖审计脚本(Linux/macOS) |
| `scripts/audit.ps1` | 依赖审计脚本(Windows) |
