Files
dstalk/docs/explanation/security-logging.md
XiuChengWu f6cb51b40a Add unit tests for OpenAI plugin and establish coding standards
- Introduced comprehensive unit tests for the OpenAI plugin, covering SSE parsing, sentinel matching, delta extraction, request building, and more.
- Created a new markdown file detailing coding and naming conventions for the dstalk project, including guidelines for comments, naming rules, code organization, and memory management practices.
2026-05-31 00:51:59 +08:00

110 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Security Logging Audit (W9.3): 错误日志凭证泄露审计
**审计人**: 曹武 (security-cao)
**日期**: 2026-05-27
**审计范围**: 8 个核心/插件源码文件
**结论**: 未发现真实凭证泄露漏洞CVSS 不适用,零高危/中危/低危可利用漏洞)
---
## 审计方法论
对每个文件搜索以下输出调用:
- `host->log(...)` / `g_host->log(...)` (插件日志 API)
- `printf` / `fprintf(stderr, ...)` (C 标准输出)
- `std::cerr` / `std::cout` (C++ 标准流)
对每个匹配项检查其格式字符串和参数是否包含 `api_key``Authorization` header、`token` 或原始 request body/headers。
## 文件清单
### 1. `plugins/openai/src/openai_plugin.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| 242-245 | `g_host->log(INFO, ...)` | 输出 model / base_url / max_tokens / temperature | 无 -- api_key 被有意排除在格式字符串外 |
| 442 | `g_host->log(ERROR, ...)` | 静态字符串 "http service not found" | 无 |
| 446 | `g_host->log(INFO, ...)` | 静态字符串 "initializing OpenAI-compatible AI plugin" | 无 |
| 453 | `g_host->log(INFO, ...)` | 静态字符串 "shutdown" | 无 |
**build_headers_json() (行 59-63)**: 构建 `{"Authorization":"Bearer <key>"}` 并传给 HTTP 服务。该字符串从未传递给任何 log 调用,仅在 `http_post_json()` / `http_post_stream()` 的参数链中使用,最终由 Beast 直接设置到 HTTP request headers -- 全程无日志记录。
**parse_response() 错误路径 (行 135-151)**: HTTP 错误响应体仅用于提取 JSON `error.message` 字段放入 `r.error`,不会输出到日志。原始 response_body 在解析后被 `g_host->free()` 释放。
### 2. `plugins/anthropic/src/anthropic_plugin.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| 247-250 | `g_host->log(INFO, ...)` | 输出 model / base_url / max_tokens / temperature | 无 -- api_key 被有意排除 |
| 453 | `g_host->log(ERROR, ...)` | 静态字符串 "http service not found" | 无 |
| 457 | `g_host->log(INFO, ...)` | 静态字符串 "initializing Anthropic AI plugin" | 无 |
| 464 | `g_host->log(INFO, ...)` | 静态字符串 "shutdown" | 无 |
**build_headers_json() (行 59-65)**: 构建 `{"x-api-key":"<key>","anthropic-version":"2023-06-01"}` 仅用于 HTTP 请求,不经过日志路径。
### 3. `plugins/network/src/network_plugin.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| -- | 无任何 `host->log` / `printf` / `cerr` 调用 | -- | 无 |
**parse_headers_json() (行 40-80)**: 解析包含 api_key 的 headers JSON 字符串。解析结果仅用于 `req.set(h.first, h.second)` (行 176) 设置 HTTP header不输出日志。
**do_post_stream() 异常路径 (行 280-282)**: `catch (std::exception& e)``e.what()` 赋值给 `result_body`。Beast/ASIO 异常消息为 OS 级别错误描述(如 "Connection refused"),不含 HTTP header/body 内容。
### 4. `plugins/config/src/config_plugin.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| -- | 无任何日志调用 | -- | 无 |
ConfigStore 仅提供 get/set/load_file无日志输出。
### 5. `dstalk-core/src/host.cpp` -- 基础设施(不动)
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| 48,51,52 | `fprintf(stderr, ...)` | 日志前缀 + vfprintf(格式,参数) + 换行 | 无 -- 基础设施自身不包含业务数据 |
该文件是日志基础设施 (`host_log_impl`),仅负责格式化输出。安全性依赖于调用方不传敏感数据(本审计已确认所有调用方均安全)。按 W9.3 禁忌不修改此文件。
### 6. `dstalk-core/src/plugin_loader.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| -- | 无任何日志调用 | -- | 无 |
### 7. `plugins/session/src/session_plugin.cpp` -- 安全
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| 233 | `host->log(ERROR, ...)` | 静态字符串 "required service 'file_io' not found" | 无 |
该插件处理消息内容role/content但不记录任何消息数据到日志。
### 8. `plugins/lsp/src/lsp_plugin.cpp` -- 低风险
| 行号 | 调用 | 内容 | 风险 |
|------|------|------|------|
| 446 | `g_host->log(ERROR, ...)` | 静态字符串 "Invalid LSP frame..." | 无 |
| 479 | `g_host->log(ERROR, ...)` | `"failed to start: %s", server_cmd` | 低 -- 理论上 server_cmd 可能含令牌,但实际为 LSP 服务器路径(如 `clangd`),不属于 API 密钥范畴 |
| 525 | `g_host->log(ERROR, ...)` | 静态字符串 "initialize timed out" | 无 |
| 535 | `g_host->log(INFO, ...)` | `"server started: %s", server_cmd` | 低 -- 同上 |
| 565 | `g_host->log(INFO, ...)` | 静态字符串 "server stopped" | 无 |
| 720 | `g_host->log(INFO, ...)` | 静态字符串 "initializing LSP service plugin" | 无 |
| 728 | `g_host->log(INFO, ...)` | 静态字符串 "shutdown" | 无 |
`server_cmd` 是启动 LSP 子进程的命令行(例如 `clangd --log=error`),不是 API 密钥或 token。若用户将 API key 嵌入命令行(极不寻常且不安全的使用方式),则存在理论泄漏风险。判断为**低风险/假阳性**,不做代码修改。
## 总结
| 风险等级 | 数量 | 说明 |
|----------|------|------|
| 严重 (CVSS 9.0+) | 0 | 无 |
| 高危 (CVSS 7.0-8.9) | 0 | 无 |
| 中危 (CVSS 4.0-6.9) | 0 | 无 |
| 低危 (CVSS 0.1-3.9) | 0 | 无真实可利用漏洞 |
| 低风险/假阳性 | 2 | 仅 lsp `server_cmd` 日志和 network `e.what()` 理论上可能暴露非凭证信息 |
**审计结论**: 所有日志输出路径均已检查,证实 OpenAI-compatible 和 Anthropic 插件的 `my_configure()` 日志有意排除了 `api_key` 字段。HTTP headers 中的凭证仅通过内存传递至 Beast HTTP 请求对象,从未进入日志管道。代码库对此攻击面防御充分,无需修改。