im_wower
·
2026-03-29
T-BUG-027.md
1# Task T-BUG-027:修复安全和资源泄漏问题
2
3## 状态
4
5- 当前状态:`已完成`
6- 规模预估:`M`
7- 依赖任务:无
8- 建议执行者:`Claude`(涉及安全修复和 async 生命周期管理,需要理解多个模块的交互)
9
10## 直接给对话的提示词
11
12读 `/Users/george/code/baa-conductor/tasks/T-BUG-027.md` 任务文档,完成开发任务。
13
14## 当前基线
15
16- 仓库:`/Users/george/code/baa-conductor`
17- 分支基线:`main`
18- 提交:`f26dd00`
19
20## 分支与 worktree(强制)
21
22每个任务必须使用独立的分支和 worktree,禁止直接在 main 上修改,禁止多个任务共用同一个 worktree。
23
24- 分支名:`bug/security-and-resource-leaks`
25- worktree 路径:`/Users/george/code/baa-conductor-security-and-resource-leaks`
26
27开工步骤:
28
291. `cd /Users/george/code/baa-conductor`
302. `git worktree add ../baa-conductor-security-and-resource-leaks -b bug/security-and-resource-leaks main`
313. `cd ../baa-conductor-security-and-resource-leaks`
324. 在这个 worktree 目录里开发,不要回到主仓库目录
33
34完成后提交与推送(由执行者完成,不要合并):
35
361. 在 worktree 里提交所有变更(包括更新后的任务文档)
372. `git push -u origin bug/security-and-resource-leaks`
38
39## 目标
40
41修复代码审查发现的 5 个安全和资源泄漏问题。
42
43## 背景
44
45代码审查发现 d1-client sync-worker 有 SQL 注入风险、D1 schema 缺外键、claude-coded daemon 有资源泄漏(未 await stop、事件监听未清理、stderr 无错误处理)。
46
47## 涉及仓库
48
49- `/Users/george/code/baa-conductor`
50
51## 允许修改的目录
52
53- `/Users/george/code/baa-conductor/packages/d1-client/src/`
54- `/Users/george/code/baa-conductor/apps/claude-coded/src/`
55- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
56
57## 尽量不要修改
58
59- `/Users/george/code/baa-conductor/packages/artifact-db/`
60- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts`
61- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/instructions/`
62- `/Users/george/code/baa-conductor/plugins/`
63
64## 必须完成
65
66### 1. 修复 SQL 注入风险
67
68**文件**:`packages/d1-client/src/sync-worker.ts` 的 `buildSyncSql` 函数
69
70**问题**:表名和列名从 sync queue payload 直接拼接到 SQL,未做校验。
71
72**修复方案**:
73- 定义允许的表名白名单:`messages`、`executions`、`sessions`
74- 定义每张表允许的列名白名单(参照 artifact-db schema)
75- `buildSyncSql` 中校验 tableName 和所有 payload key 是否在白名单内,不在则拒绝并返回 null
76- 不要用正则校验列名,用显式白名单
77
78### 2. 修复 D1 schema 缺外键
79
80**文件**:`packages/d1-client/src/d1-setup.sql`
81
82**问题**:executions 表缺少 `FOREIGN KEY (message_id) REFERENCES messages(id)`,本地 artifact-db 有但 D1 没有。
83
84**修复方案**:
85- 在 d1-setup.sql 的 executions 表定义中加上 `FOREIGN KEY (message_id) REFERENCES messages(id)`
86- 确保与 `packages/artifact-db/src/schema.ts` 的 executions 表定义一致
87
88### 3. 修复 daemon.stop() 未 await
89
90**文件**:`apps/conductor-daemon/src/index.ts`
91
92**问题**:`start()` 错误处理和 `stop()` 方法中调 `daemon.stop()` 没有 await,可能留孤儿进程。
93
94**修复方案**:
95- `start()` 错误处理中的 `this.daemon.stop()` 改为 `await this.daemon.stop()`
96- `stop()` 方法中的 `this.daemon.stop()` 改为 `await this.daemon.stop()`
97
98### 4. 修复 stdio 事件监听未清理
99
100**文件**:`apps/claude-coded/src/stream-json-transport.ts`
101
102**问题**:`connect()` 注册了多个事件监听器(stdout data/end/error、stderr data、process error/exit),`close()` 只关了 stdin,重连会累积监听器。
103
104**修复方案**:
105- 保存所有注册的监听器引用
106- `close()` 中用 `off()` 移除所有监听器
107- 或者改用 `once()` 对于一次性事件
108
109### 5. 修复 stderr 无错误处理
110
111**文件**:`apps/claude-coded/src/stream-json-transport.ts`
112
113**问题**:stderr 流没有注册 error handler,未捕获的 stderr 错误可能导致进程崩溃。
114
115**修复方案**:
116- 给 stderr 注册 `error` 事件处理器,捕获并记录错误
117- 同样需要在 `close()` 中清理
118
119## 需要特别注意
120
121- SQL 注入修复要用显式白名单,不要用正则(正则容易绕过)
122- daemon.stop() 的 await 修复要注意不要引入死锁(stop 等待子进程退出,子进程可能等待 stdin 关闭)
123- 事件监听清理要确保不会影响正常的连接/断开流程
124- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
125
126## 验收标准
127
128- `buildSyncSql` 对非白名单表名返回 null
129- `buildSyncSql` 对非白名单列名过滤掉或返回 null
130- `d1-setup.sql` 的 executions 表有外键约束
131- conductor stop 时无孤儿进程
132- claude-coded transport 重连不累积监听器
133- stderr 错误不导致进程崩溃
134- 所有现有测试通过
135
136## 推荐验证命令
137
138- `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm build`
139- `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm test`
140
141## 执行记录
142
143> 以下内容由执行任务的 AI 填写,创建任务时留空。
144
145### 开始执行
146
147- 执行者:`Codex (GPT-5)`
148- 开始时间:`2026-03-29 02:02:36 +0800`
149- 状态变更:`待开始` → `进行中`
150
151### 完成摘要
152
153- 完成时间:`2026-03-29 02:12:55 +0800`
154- 状态变更:`进行中` → `已完成`
155- 修改了哪些文件:
156 - `packages/d1-client/src/sync-worker.ts`
157 - `packages/d1-client/src/d1-setup.sql`
158 - `packages/d1-client/src/index.test.js`
159 - `apps/claude-coded/src/stream-json-transport.ts`
160 - `apps/claude-coded/src/daemon.ts`
161 - `apps/claude-coded/src/stream-json-transport.test.js`
162 - `apps/conductor-daemon/src/index.ts`
163 - `apps/conductor-daemon/src/index.test.js`
164 - `tasks/T-BUG-027.md`
165- 核心实现思路:
166 - 为 D1 sync SQL 生成增加显式表名/列名白名单,遇到非白名单表或列直接拒绝同步,避免从 sync queue payload 拼接 SQL 标识符。
167 - 让 D1 schema 的 `executions.message_id` 与本地 artifact-db schema 对齐,补上外键约束。
168 - 为 `stream-json-transport` 保存并清理 stdio/process 监听器,在 `close()` 和异常关闭路径都解绑;同时为 `stderr` 增加 `error` handler,并把诊断上报到 daemon 事件流。
169 - 在 `ConductorRuntime.start()` 的本地 API 启动失败路径和 `stop()` 路径都 `await this.daemon.stop()`,确保子进程停止完成后再继续收尾。
170- 跑了哪些测试:
171 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm --filter @baa-conductor/d1-client test`
172 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm --filter @baa-conductor/claude-coded build`
173 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && node --test apps/claude-coded/src/stream-json-transport.test.js`
174 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm --filter @baa-conductor/conductor-daemon test`
175 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm build`
176 - `cd /Users/george/code/baa-conductor-security-and-resource-leaks && pnpm test`
177
178### 执行过程中遇到的问题
179
180> 记录执行过程中遇到的阻塞、环境问题、临时绕过方案等。合并时由合并者判断是否需要修复或建新任务。
181
182- 新建 worktree 后缺少依赖,`pnpm exec tsc` 无法找到 `tsc`。已在独立 worktree 中执行 `pnpm install` 后继续开发和验证。
183- 仓库级 `pnpm test` 默认不覆盖 `@baa-conductor/d1-client` 和 `@baa-conductor/claude-coded`,因此额外单独执行了这两处的定向测试。
184
185### 剩余风险
186
187- `claude-coded` 的 transport 回归测试目前通过单独的 `node --test` 执行,尚未接入仓库级 `verify-workspace.mjs test` 流程。