## 跨站脚本攻击 XSS（High）

### 触发信号

- 用户输入直接拼接到 HTML 响应体（`innerHTML`、模板字面量拼接到 HTML）
- `document.write()`、`document.writeln()` 接收用户输入
- `eval()`、`Function()`、`setTimeout(string)`、`setInterval(string)` 执行用户输入
- URL hash/query 参数被直接插入 DOM
- 框架的 `dangerouslySetInnerHTML`、`v-html`、`[innerHTML]` 接收用户输入

### 关键 Sink

| XSS 类型 | Sink 函数/模式 |
|---------|---------------|
| 反射型 XSS | `res.send(user_input)`、`response.write(user_input)`、模板引擎未转义输出 |
| 存储型 XSS | 存储后未转义即输出（数据库存入 → 读取 → 直接渲染到 HTML） |
| DOM 型 XSS | `element.innerHTML = input`、`document.write(input)`、`$(element).html(input)` |
| JS 执行 | `eval(input)`、`setTimeout(input)`、`new Function(input)` |

### 判定流程

1. **识别 Sink**：`Read` 提取 HTML 输出和 JS 执行操作，标记 Sink 点
2. **反向追踪 Source**：`find_references` 从 Sink 参数反向追踪（最多 5 层），判断数据是否来自用户输入
3. **检查上下文**：`Read` 确认 Sink 的输出上下文：
   - HTML 内容（需要 HTML 实体转义）
   - HTML 属性（需要属性值转义）
   - JavaScript 代码（需要 JS 转义）
   - URL（需要 URL 编码）
   - CSS（需要 CSS 转义）
4. **检查防御机制**：`Read` 确认是否存在：
   - 框架自动转义（React JSX、Vue `{{ }}` 默认转义）
   - 显式转义函数（`escapeHtml`、`DOMPurify.sanitize`）
   - Content-Security-Policy 头（限制脚本执行来源）
   - `HttpOnly` cookie 标记（防止 cookie 被窃取）

### 证据构造

确认缺陷后，输出需包含：
- Source（用户输入来源，含文件:行号）
- Sink（未转义的输出/执行位置，含文件:行号）
- 输出上下文（HTML 内容/属性/JS/URL/CSS）
- 利用场景（具体的 XSS payload 示例，如 `<script>alert(1)</script>`）

### 排除

- 框架默认转义保护（React JSX、Vue `{{ }}`、Angular 插值）
- 已使用 `DOMPurify` 或等效库进行净化
- 已设置 CSP 头且未使用 `unsafe-inline`/`unsafe-eval`
- 纯 JSON API 响应（Content-Type 为 application/json，非 HTML）
