Skip to content

fix: 修复 15 个安全和逻辑 bug (CRITICAL/HIGH/MEDIUM)#13

Closed
colin1112a wants to merge 1 commit into
dwgx:masterfrom
colin1112a:fix/security-and-bugs-15-issues
Closed

fix: 修复 15 个安全和逻辑 bug (CRITICAL/HIGH/MEDIUM)#13
colin1112a wants to merge 1 commit into
dwgx:masterfrom
colin1112a:fix/security-and-bugs-15-issues

Conversation

@colin1112a
Copy link
Copy Markdown
Contributor

概述

修复项目审查中发现的 15 个严重 bug,涵盖 2 个 CRITICAL、5 个 HIGH、8 个 MEDIUM 级别问题。

Security 安全修复 (CRITICAL/HIGH)

  • /auth/* 路由移至 API key 验证之后,防止未授权访问
  • getAccountList 移除完整 apiKey 字段,仅保留 keyPrefix
  • readBody 添加 10MB 大小限制,防止 OOM DoS
  • ✅ 所有 dashboard onclick 处理器中的动态值使用 esc() 转义,防止 XSS
  • ✅ git branch 名校验,防止 shell 注入
  • ✅ langserver proxyKey 清理特殊字符,防止 shell 注入
  • ✅ SSE 日志流改用 fetch + header 传递密码,避免 URL 泄露

Correctness 正确性修复 (CRITICAL/HIGH)

  • _msgChars 变量提升到 for 循环外,修复 catch 块 ReferenceError
  • markRateLimited 调用传递正确参数 (apiKey, duration, modelKey)
  • saveAccounts 使用原子写入 (write-to-temp + rename)
  • ✅ 流式重试时重新分配 parser/sanitizer,避免脏状态

Resource Management 资源管理 (HIGH/MEDIUM)

  • ✅ grpc 添加 HTTP/2 session pool,避免端口耗尽
  • grpcUnary 添加 settled flag,防止 double-reject
  • grpcStream 添加 done flag,防止 onError/onEnd 双回调
  • rawGetChatMessage 添加 done flag,reject 后停止流处理
  • ensureLs 添加 _pending Map,防止并发竞态产生孤儿进程
  • StreamingFrameParser 添加 16MB 帧大小上限

Protocol 协议修复 (MEDIUM)

  • ✅ varint encode/decode 支持 >32 位值,使用 BigInt 处理

Dashboard 补充

  • ✅ model-access.js 和 proxy-config.js 添加错误日志

影响范围

  • 文件数: 12 个文件
  • 代码变更: +284 行 / -162 行
  • 测试: 语法检查通过,服务正常启动,LS 就绪,无错误日志

验证步骤

# 语法检查
node --check src/*.js src/handlers/*.js src/dashboard/*.js

# 重启服务
pm2 restart windsurf-api

# 验证 apiKey 不再泄露
curl http://localhost:3003/auth/accounts | grep -i apikey  # 应无输出

## Security 安全修复 (CRITICAL/HIGH)
- fix: /auth/* 路由移至 API key 验证之后,防止未授权访问
- fix: getAccountList 移除完整 apiKey 字段,仅保留 keyPrefix
- fix: readBody 添加 10MB 大小限制,防止 OOM DoS
- fix: 所有 dashboard onclick 处理器中的动态值使用 esc() 转义,防止 XSS
- fix: git branch 名校验,防止 shell 注入
- fix: langserver proxyKey 清理特殊字符,防止 shell 注入
- fix: SSE 日志流改用 fetch + header 传递密码,避免 URL 泄露

## Correctness 正确性修复 (CRITICAL/HIGH)
- fix: _msgChars 变量提升到 for 循环外,修复 catch 块 ReferenceError
- fix: markRateLimited 调用传递正确参数 (apiKey, duration, modelKey)
- fix: saveAccounts 使用原子写入 (write-to-temp + rename)
- fix: 流式重试时重新分配 parser/sanitizer,避免脏状态

## Resource Management 资源管理 (HIGH/MEDIUM)
- fix: grpc 添加 HTTP/2 session pool,避免端口耗尽
- fix: grpcUnary 添加 settled flag,防止 double-reject
- fix: grpcStream 添加 done flag,防止 onError/onEnd 双回调
- fix: rawGetChatMessage 添加 done flag,reject 后停止流处理
- fix: ensureLs 添加 _pending Map,防止并发竞态产生孤儿进程
- fix: StreamingFrameParser 添加 16MB 帧大小上限

## Protocol 协议修复 (MEDIUM)
- fix: varint encode/decode 支持 >32 位值,使用 BigInt 处理

## Dashboard 补充
- fix: model-access.js 和 proxy-config.js 添加错误日志

影响范围:12 个文件,涵盖认证、资源管理、协议解析、XSS 防护
测试:语法检查通过,服务正常启动,LS 就绪,无错误日志
@colin1112a
Copy link
Copy Markdown
Contributor Author

拿cc写的
你这玩意全是洞:)

@dwgx
Copy link
Copy Markdown
Owner

dwgx commented Apr 21, 2026

无语无语 行 我自己随便public的 谁知道这么多人来forkstar 懂吧 所以我也在重视issus 谢谢你!!

dwgx added a commit that referenced this pull request Apr 21, 2026
auth.js  原子写 saveAccounts (tmp + rename),与现有 _saveInFlight mutex 组合
client.js  rawGetChatMessage done flag 防 onEnd/onError 双回调
connect.js  StreamingFrameParser 16MB 帧上限
server.js  readBody 10MB 上限 (413)
grpc.js  HTTP/2 session 池(一端口一 session)+ settle-once guards + closeSessionForPort()
langserver.js  _pending map 合并并发 ensureLs;proxyKey [^A-Za-z0-9_] 全清;LS exit 时关对应 session
dashboard/api.js  self-update git branch 走 regex 校验
dashboard/index.html
  - XSS: 补齐 PR 漏掉的 refreshCredits / resetErrors / 封禁面板按钮 / proxy 表格等 onclick 的 esc
  - loadLogs 改 fetch + ReadableStream + X-Dashboard-Password header(?pwd= 兜底保留)
dashboard/{model-access,proxy-config}.js  load/save 失败加 log.error

重复 (d020525 已有更好实现,未采纳 PR 版本):chat.js _msgChars / markRateLimited 参数 / proto.js varint BigInt
不采纳:getAccountList 去 apiKey 会坏 dashboard 复制功能;/auth 路由反而开口 /auth/status
@dwgx dwgx closed this Apr 21, 2026
dwgx added a commit that referenced this pull request Apr 21, 2026
Dashboard 侧栏新增"关于 → 致谢"面板,列出外部贡献者:
- dd373156 — PR #1 修 Pro 层模型合并
- colin1112a — PR #13 一次性审 15 个 bug

卡片含 GitHub 头像(github.com/:user.png)、PR 链接、合并日期、改动说明。CONTRIBUTORS 数组手动维护,后续有 PR 直接加一项就能渲染。底部放"提 issue / 提 PR"按钮鼓励继续贡献。

README.md / README.en.md 也加了对应的 Contributors 段放在 MIT 前。
dwgx added a commit that referenced this pull request Apr 21, 2026
PR #13 技术上被 close 而不是 merged(rebase 冲突 + master 有更干净实现),
但 colin1112a 的审计方向和 8 处具体修复都被吸收到了 d811f56 里,加固的
escJsAttr / _pending coalesce / pooled session cleanup 也都沿着他的路线
延伸出来。用 Co-authored-by 把他正式登记进仓库贡献者列表,不要因为 PR
状态是 closed 就埋没他的工作。

Co-authored-by: colin1112a <218527967+colin1112a@users.noreply.github.com>
dwgx added a commit that referenced this pull request Apr 21, 2026
auth.js  原子写 saveAccounts (tmp + rename),与现有 _saveInFlight mutex 组合
client.js  rawGetChatMessage done flag 防 onEnd/onError 双回调
connect.js  StreamingFrameParser 16MB 帧上限
server.js  readBody 10MB 上限 (413)
grpc.js  HTTP/2 session 池(一端口一 session)+ settle-once guards + closeSessionForPort()
langserver.js  _pending map 合并并发 ensureLs;proxyKey [^A-Za-z0-9_] 全清;LS exit 时关对应 session
dashboard/api.js  self-update git branch 走 regex 校验
dashboard/index.html
  - XSS: 补齐 PR 漏掉的 refreshCredits / resetErrors / 封禁面板按钮 / proxy 表格等 onclick 的 esc
  - loadLogs 改 fetch + ReadableStream + X-Dashboard-Password header(?pwd= 兜底保留)
dashboard/{model-access,proxy-config}.js  load/save 失败加 log.error

重复 (d020525 已有更好实现,未采纳 PR 版本):chat.js _msgChars / markRateLimited 参数 / proto.js varint BigInt
不采纳:getAccountList 去 apiKey 会坏 dashboard 复制功能;/auth 路由反而开口 /auth/status
dwgx added a commit that referenced this pull request Apr 21, 2026
Dashboard 侧栏新增"关于 → 致谢"面板,列出外部贡献者:
- dd373156 — PR #1 修 Pro 层模型合并
- colin1112a — PR #13 一次性审 15 个 bug

卡片含 GitHub 头像(github.com/:user.png)、PR 链接、合并日期、改动说明。CONTRIBUTORS 数组手动维护,后续有 PR 直接加一项就能渲染。底部放"提 issue / 提 PR"按钮鼓励继续贡献。

README.md / README.en.md 也加了对应的 Contributors 段放在 MIT 前。
dwgx added a commit that referenced this pull request Apr 21, 2026
PR #13 技术上被 close 而不是 merged(rebase 冲突 + master 有更干净实现),
但 colin1112a 的审计方向和 8 处具体修复都被吸收到了 d811f56 里,加固的
escJsAttr / _pending coalesce / pooled session cleanup 也都沿着他的路线
延伸出来。用 Co-authored-by 把他正式登记进仓库贡献者列表,不要因为 PR
状态是 closed 就埋没他的工作。

Co-authored-by: colin1112a <218527967+colin1112a@users.noreply.github.com>
dwgx added a commit that referenced this pull request Apr 21, 2026
chat.js streamResponse  PR #13 原本要求"流式重试时重新分配 parser/sanitizer
避免脏状态",之前合并时漏了。把 toolParser / pathStreamText / pathStreamThinking
的创建移进 for 循环,attempt>0 且 !hadSuccess 时重建,防止前一次失败的半读
<tool_call> 片段或 hold-back path 残留污染下一次重试的流。

dashboard/windsurf-login.js  BUG-16: 删掉未使用的 authHeader 本地变量,
真正的 Proxy-Authorization 是通过下面 headers 对象传的。

langserver.js  BUG-17: getLsFor 不再悄悄回退到 default LS。回退会让请求走
错误的 egress IP,Codeium 看到不匹配的来源直接让会话过期,然后账号被误
判 expired。调用方必须先 ensureLs(proxy) 再 getLsFor —— 现有 chat.js
已经这么做,所以移除 fallback 没副作用。
dwgx added a commit that referenced this pull request Apr 21, 2026
auth.js  原子写 saveAccounts (tmp + rename),与现有 _saveInFlight mutex 组合
client.js  rawGetChatMessage done flag 防 onEnd/onError 双回调
connect.js  StreamingFrameParser 16MB 帧上限
server.js  readBody 10MB 上限 (413)
grpc.js  HTTP/2 session 池(一端口一 session)+ settle-once guards + closeSessionForPort()
langserver.js  _pending map 合并并发 ensureLs;proxyKey [^A-Za-z0-9_] 全清;LS exit 时关对应 session
dashboard/api.js  self-update git branch 走 regex 校验
dashboard/index.html
  - XSS: 补齐 PR 漏掉的 refreshCredits / resetErrors / 封禁面板按钮 / proxy 表格等 onclick 的 esc
  - loadLogs 改 fetch + ReadableStream + X-Dashboard-Password header(?pwd= 兜底保留)
dashboard/{model-access,proxy-config}.js  load/save 失败加 log.error

重复 (d020525 已有更好实现,未采纳 PR 版本):chat.js _msgChars / markRateLimited 参数 / proto.js varint BigInt
不采纳:getAccountList 去 apiKey 会坏 dashboard 复制功能;/auth 路由反而开口 /auth/status
dwgx added a commit that referenced this pull request Apr 21, 2026
Dashboard 侧栏新增"关于 → 致谢"面板,列出外部贡献者:
- dd373156 — PR #1 修 Pro 层模型合并
- colin1112a — PR #13 一次性审 15 个 bug

卡片含 GitHub 头像(github.com/:user.png)、PR 链接、合并日期、改动说明。CONTRIBUTORS 数组手动维护,后续有 PR 直接加一项就能渲染。底部放"提 issue / 提 PR"按钮鼓励继续贡献。

README.md / README.en.md 也加了对应的 Contributors 段放在 MIT 前。
dwgx added a commit that referenced this pull request Apr 21, 2026
chat.js streamResponse  PR #13 原本要求"流式重试时重新分配 parser/sanitizer
避免脏状态",之前合并时漏了。把 toolParser / pathStreamText / pathStreamThinking
的创建移进 for 循环,attempt>0 且 !hadSuccess 时重建,防止前一次失败的半读
<tool_call> 片段或 hold-back path 残留污染下一次重试的流。

dashboard/windsurf-login.js  BUG-16: 删掉未使用的 authHeader 本地变量,
真正的 Proxy-Authorization 是通过下面 headers 对象传的。

langserver.js  BUG-17: getLsFor 不再悄悄回退到 default LS。回退会让请求走
错误的 egress IP,Codeium 看到不匹配的来源直接让会话过期,然后账号被误
判 expired。调用方必须先 ensureLs(proxy) 再 getLsFor —— 现有 chat.js
已经这么做,所以移除 fallback 没副作用。
MYMDO added a commit to MYMDO/WindsurfAPI that referenced this pull request May 14, 2026
Operational/navigation links updated to MYMDO/WindsurfAPI:
- package.json: homepage, repository.url, bugs.url
- install-ls.sh: OUR_RELEASE
- update.sh: RELEASE_URL
- docker-compose.yml: ghcr.io/mymdo/windsurf-api:latest (lowercased per GHCR)
- SECURITY.md: 2x security advisory URLs
- .github/ISSUE_TEMPLATE/config.yml: security advisory URL
- .github/workflows/release.yml: comment
- README.{md,en,ua,zh}.md: clone URLs, GitHub Pages catalog, Issues/PR CTAs
- docs/index.html: nav GitHub, hero CTA, deploy clone, contributors CTA, footer (GitHub/Releases/Issues/Security/READMEs/CONTRIBUTING)
- src/dashboard/index.html + index-sketch.html: Issue/PR CTA buttons, RELEASE_NOTES blob link

KEPT at dwgx (intentional):
- Historical PR references (PR dwgx#1, dwgx#13, dwgx#36, dwgx#43, dwgx#44, dwgx#45) — they exist only in dwgx/WindsurfAPI
- @dwgx profile link in footer (attribution)
- (c) 2026 dwgx (copyright attribution per MIT)
- package.json author field (original creator)
- bydwgx1337 brand strings in dashboard UI / server provider / version BRAND
- contributors.json (login + historical narrative)
- test fixtures and code comments referencing dwgx
- docs/releases/RELEASE_NOTES_*.md (historical archives)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants