Wave 5+6: plugin ABI hardening, build modernization, ABI/security docs
Wave 5 (9 parallel agents): - W1.1 atomic diag callback + DLL handle release on shutdown (lin) - W2.1 unify cross-DLL heap discipline (host->alloc/free/strdup) (chen) - W2.2 secure_zero api_key on shutdown for deepseek/anthropic (cao) - W3 CMake modernization: target-based cxx_std_20, dstalk_boost_config INTERFACE lib, root-level RUNTIME_OUTPUT_DIRECTORY (hu) - W4 GitHub Actions CI with dynamic Linux/Windows matrix (ma) - W5.1 SSE buffer_body to cut peak memory ~67% on 32K streams (zhou) - W6.1 LSP JSON-RPC frame parser hardened against header reordering (sun) - W7 smoke test: copy plugin DLLs post-build + Boost.JSON src.hpp fix for full 9-plugin load coverage (wang) - W8.1 README slimmed 398->92, Diataxis docs/ skeleton (deng) Wave 6 (6 parallel agents): - W9.1 docs/explanation: architecture + plugin-lifecycle (deng) - W9.3 log credential leak audit (0 vulns, audit trail in docs/explanation/security-logging.md) (cao) - W9.4 docs/reference/plugin-abi.md - 7-point ABI contract (lin) - W9.6 CLI /history command + status integration (zhao) - W9.8 plugin_loader fault tolerance: per-plugin failure no longer aborts dstalk_init (huang) - W9.10 host_api unit tests: tests/host_api_test.cpp, 8 cases (liu) CEO oversight (preexisting bugs fixed during Wave 5 verification): - lsp_plugin.cpp:449 forward decl mismatch (int vs void) - tools_plugin.cpp:109 missing forward decl Multi-agent collaboration framework: - agents/WORKFLOW.md: 6-stage protocol, two-tier governance, prompt template, technical constraints registry Build: cmake --build 0 error / 0 warning. Tests: 2/2 100% pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
109
docs/explanation/security-logging.md
Normal file
109
docs/explanation/security-logging.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# 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/deepseek/src/deepseek_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 DeepSeek 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()` 理论上可能暴露非凭证信息 |
|
||||
|
||||
**审计结论**: 所有日志输出路径均已检查,证实 DeepSeek 和 Anthropic 插件的 `my_configure()` 日志有意排除了 `api_key` 字段。HTTP headers 中的凭证仅通过内存传递至 Beast HTTP 请求对象,从未进入日志管道。代码库对此攻击面防御充分,无需修改。
|
||||
Reference in New Issue
Block a user