## 敏感数据泄露（Medium）

### 触发信号

- `console.log`/`logger.info`/`logger.debug` 输出包含敏感字段
- 错误响应中暴露堆栈/内部信息（`err.stack`、`ex.toString()` 直接返回给客户端）
- API 响应中包含不应暴露的字段（密码哈希、内部 ID、完整身份证号）
- 日志配置为 debug/verbose 级别且输出请求体

### 关键 Sink

| 泄露类型 | Sink 位置 |
|---------|----------|
| 日志泄露 | `console.log()`、`logger.info()`、`logger.debug()` 输出含敏感数据 |
| 错误信息泄露 | `res.status(500).json({ error: err.stack })`、`response.send(ex.message)` |
| 响应字段泄露 | API 返回了 `password`、`creditCard`、`ssn`、`internalId` 等字段 |
| 调试信息泄露 | `debug=True`（Flask）、`NODE_ENV=development`、`DEBUG=1` |

### 判定流程

1. **检查日志输出**：`Grep` 搜索 `console.log`、`logger` 调用，`Read` 检查输出内容是否包含：
   - 密码、Token、API Key、Session ID
   - 身份证号、手机号、银行卡号
   - 完整的请求体（可能含敏感字段）
2. **检查错误响应**：`Read` 确认错误处理是否向客户端暴露了内部信息：
   - 完整堆栈信息（`err.stack`）
   - 内部路径（`/app/services/user.js:42`）
   - 数据库错误详情（SQL 语句、表名）
   - 应返回通用错误信息给客户端，详细错误仅记录到日志
3. **检查 API 响应字段**：`Read` 确认序列化/返回逻辑是否过滤了敏感字段：
   - 用户对象是否排除了 `password`/`salt`/`creditCard`
   - 是否使用了 `toJSON()`/`@JsonIgnore`/`exclude` 过滤
4. **检查调试配置**：`Read` 确认生产环境是否关闭了调试模式：
   - 是否有环境判断（`if (process.env.NODE_ENV === 'production')`）

### 证据构造

确认缺陷后，输出需包含：
- 泄露位置（日志/响应/配置，含文件:行号）
- 泄露的敏感数据类型（密码/Token/身份证/堆栈）
- 攻击向量（日志访问、错误信息收集、响应字段分析）
- 业务影响（信息收集为后续攻击提供素材、合规违规）

### 排除

- 日志输出已脱敏（密码显示为 `***`、Token 仅显示前4位）
- 敏感字段已通过 `@JsonIgnore`/`toJSON()`/`exclude` 过滤
- 错误响应已区分内部日志和客户端响应
- 生产环境配置已关闭调试模式（通过环境变量判断）
