This was generated by AI during triage.
审计范围
审计基于 master 当前提交 d98a29600(v4.26.6),覆盖:
FastAPI Dashboard API、认证授权、插件/技能、备份恢复、更新、文件接口、沙箱生命周期
Vue Dashboard API、iframe/plugin page、上传、SSE、依赖供应链
GitHub Actions、发布流程、Python/Node 依赖可复现性、测试入口
当前开放 issues 与 PRs,重点检查是否已有完整修复
本地验证:
uv run ruff check .:通过
uv run ruff format --check .:480 files already formatted
uv run pytest tests/test_fastapi_v1_dashboard.py tests/test_backup.py tests/test_shipyard_neo_booter.py -q:146 passed
cd dashboard && pnpm typecheck:通过
cd dashboard && pnpm audit --prod --json:4 low / 35 moderate / 18 high
优先级总览
优先级
数量
建议时限
P0
3 个现有公开安全问题
立即阻断或限制暴露面
P1
7 个高风险问题
下一补丁版本前完成
P2
4 个稳定性/DoS 问题
近期迭代完成
P3
2 个长期风险
排期修复
P0:已有公开安全问题
P0-1 多处 SSRF 仍需统一出口策略
P0-2 插件安装链路等价于进程内代码执行
P0-3 MCP 配置可启动任意本地命令
P1:高风险问题
P1-1 插件页面资源令牌与 Dashboard 会话 JWT 类型混淆
位置:astrbot/dashboard/api/auth.py:145-173、astrbot/dashboard/services/plugin_page_service.py:894-919
状态:已代码级确认;暂无 issue/PR。
影响:用途受限、短时效的 plugin page asset token 可被通用 API JWT 校验路径接受为全权限 Dashboard 身份。
公开说明:完整复现细节不在公开 issue 展开,建议维护者转入 GitHub Security Advisory 处理。
修复指导:Dashboard session JWT 必须验证固定 token_type、aud、iss;资源 token 使用独立签名密钥和独立 decode 函数;require_scope() 明确拒绝非 session token;增加“asset token 请求 system endpoint 必须 401/403”的回归测试。
P1-2 备份知识库元数据可使写入路径逃逸可信根目录
位置:astrbot/core/backup/importer.py:744-789
状态:已代码级确认;暂无完整修复。
影响:不可信备份中的知识库标识被直接拼入目录路径,现有校验只验证目标位于这个已被污染的目录内,不能保证仍在知识库根目录下。
相关 PR:fix: reject invalid backup uploads #9130 仅拒绝缺失/无效 manifest.json 的 ZIP,不能修复此路径问题。
修复指导:严格限制知识库 ID 字符集和长度;拒绝绝对路径、分隔符、.、..;最终目录必须相对可信 kb_root_dir;所有安全预检必须在清库和写文件前完成;增加临时目录外写入回归测试。
P1-3 Dashboard/文件下载在证书错误后默认关闭 TLS 验证
位置:astrbot/core/utils/io.py:276-344、astrbot/core/utils/io.py:508-600
状态:暂无 issue/PR。
影响:更新资源在证书校验失败时自动以 CERT_NONE 重试,网络路径攻击者可替换下载内容;ZIP 格式检查不提供来源完整性保证。
修复指导:更新、插件、技能等代码/资源下载必须 fail closed;默认删除 insecure fallback;官方发布包增加签名验证;如为兼容私有部署保留开关,必须默认关闭且不能用于官方更新链路。
P1-4 Dashboard 生产依赖存在 18 个 high advisories,CI 不阻断
位置:dashboard/package.json、dashboard/pnpm-lock.yaml、.github/workflows/dashboard_ci.yml
状态:审计命令确认 18 high。
涉及:Axios、Lodash/Lodash-es、Vite、DOMPurify、Mermaid、Linkify-it 等。
相关 PR:fix: harden runtime and supply chain security #6116 描述声称升级依赖,但当前 PR diff 不包含 dashboard/package.json 或 dashboard/pnpm-lock.yaml,不能视为依赖修复。
修复指导:单独提交依赖修复 PR;升级到 audit 提示的 patched versions;加入 pnpm audit --prod --audit-level high 门禁;Dependabot 增加 /dashboard npm ecosystem;无法立即升级的项目建立有到期日的精确 allowlist。
P1-5 手动 release 可把一个 ref 的源码发布到另一个 tag
位置:.github/workflows/release.yml:7-15,30-51,130-151,210-231
状态:暂无 issue/PR。
影响:workflow_dispatch 独立接收 ref 和 tag,未验证 checkout HEAD、tag commit、pyproject.toml version 三者一致,可能产生标签、源码、PyPI wheel、Release asset 不一致。
修复指导:手动发布只接受 tag 并 checkout 该 tag;发布前强制验证 HEAD == tag commit 且 tag == v${project.version};禁止覆盖既有 release asset,除非显式受控重发流程。
P1-6 tag 发布未依赖测试、wheel smoke、依赖审计
位置:.github/workflows/release.yml、.github/workflows/docker-image.yml
状态:暂无完整修复。
相关 PR:feat(ci): introduce unified CI Required Gate workflow #6835 改善 PR 主分支门禁,但不覆盖 tag release,且未加入依赖审计。
修复指导:建立可复用 release verification workflow;发布 job 必须依赖完整 pytest、Dashboard frozen build、Python/Node audit、uv build、安装 wheel 后启动 smoke;验证通过后才允许 PyPI、GitHub Release、R2 和 Docker push。
P1-7 Python/Node 发布依赖不可复现
位置:.gitignore:6、scripts/run_pytests_ci.sh:18-20、.github/workflows/docker-image.yml:47-63,161-171、scripts/hatch_build.py:47-62
状态:Python uv.lock 未跟踪;Docker/Hatch 使用 npm install,绕过唯一提交的 pnpm-lock.yaml。
相关 PR:fix #5089: remove uv.lock from gitignore #5090 方向正确,但当前 lock 已落后主线,且 PR 未把 CI/Docker 改为 frozen 模式,不能原样合并。
修复指导:在最新 master 重新生成并提交 uv.lock;CI 用 uv sync --frozen --group dev;Docker/export 禁止构建时重新 lock;所有 Dashboard 构建统一固定 pnpm 并使用 pnpm install --frozen-lockfile;package.json 声明 packageManager。
P2:稳定性与资源耗尽
P2-1 备份上传/导入缺少统一资源预算
位置:astrbot/dashboard/services/backup_service.py、astrbot/core/backup/importer.py
风险:上传大小、分片总量、ZIP 成员数、总展开大小、压缩比和单成员大小均缺少完整限制;多处整块 read() 可造成内存或磁盘耗尽。
相关 PR:fix: reject invalid backup uploads #9130 可合并,用于修复“无效 ZIP 上传后被接受和残留”;但必须另补 ZIP bomb、大小预算和路径安全。
修复指导:反向代理与应用双层限制;分片校验声明大小、实际大小和 SHA-256;ZIP 写入前预检成员数、总展开大小、单文件大小、压缩比;全程固定块流式复制。
P2-2 文件 DELETE 接口返回成功但不删除,上传无配额
位置:astrbot/dashboard/api/files.py:70-111、astrbot/dashboard/services/chat_service.py:589-637
风险:DELETE /api/v1/files/{attachment_id} 仅回显 ID;文件和 DB 记录保留。file scope 可持续上传且无文件/主体/全局配额。
修复指导:DELETE 调用实际 attachment 删除逻辑并校验所有权/引用;流式上传累计字节并在超限时清理临时文件;增加每 key 和全局配额;测试上传、删除、DB 记录、磁盘文件一致性。
P2-3 Shipyard Neo 启动异常会泄漏 client/远端 sandbox
位置:astrbot/core/computer/booters/shipyard_neo.py:396-463
风险:client 已进入、sandbox 已创建后,profile/readiness 网络异常或任务取消没有统一清理,可能留下连接和计费资源。
修复指导:初始化用 try/except BaseException 包围;异常时先删除 sandbox,再关闭 client,清空组件字段,最后原样抛出;取消清理考虑 asyncio.shield();增加 refresh 异常和 cancellation 测试。
P2-4 Docker 手动 release tag 获取参数拼写错误
位置:.github/workflows/docker-image.yml:22-27,127-142
风险:fetch-tag: true 不是 actions/checkout 支持参数;配合 fetch-depth: 1,手动流程中的 git describe --tags 不可靠。
修复指导:改为 fetch-tags: true 和 fetch-depth: 0;随后验证 checkout HEAD 与解析 tag commit 一致。
P3:长期风险
P3-1 API key/JWT 支持 URL query 认证
位置:astrbot/dashboard/api/auth.py:44-55、Open API/Live Chat WebSocket 认证路径
风险:长期凭据进入代理日志、APM、浏览器历史和复制 URL。
修复指导:HTTP 仅接受 Authorization/X-API-Key;WebSocket 通过认证 HTTP endpoint 换取一次性短期 ticket;统一日志脱敏。
P3-2 QQ Official 会话缓存无 TTL/容量限制
位置:astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py
风险:历史唯一会话持续常驻;过期消息 ID 可能继续用于回复。
修复指导:缓存增加 TTL 和容量上限;消息 ID TTL 对齐平台回复窗口;adapter shutdown 时清空;增加大量唯一会话和过期测试。
现有 PR Review 结论
PR
结论
意见
#9130
建议合并后继续补强
无效 ZIP 校验和失败清理正确,21 checks passed;不解决路径穿越、ZIP bomb、上传预算。
#5090
需要更新后再合并
提交 lock 方向正确,6 checks passed;应 rebase 后重生成 lock,并同步改 frozen CI/Docker。
#6116
Request changes
Draft 且 Sourcery check failed;PR 过大、混合多个安全主题;正文与当前 diff 的依赖修复声明不一致。建议拆分,依赖升级独立 PR。
#6835
可作为 PR 门禁基础,不是 release 修复
目前仅 Sourcery check;应补 frozen dependency、依赖审计,并让 release workflow 显式复用验证结果。
建议执行顺序
立即私下修复 P1-1、P1-2,并轮换可能泄漏的 token/key。
关闭官方更新链路 TLS 降级;升级 Dashboard 高危依赖。
合并并扩展 fix: reject invalid backup uploads #9130 ;更新 fix #5089: remove uv.lock from gitignore #5090 ;拆分 fix: harden runtime and supply chain security #6116 。
修复 release/tag 一致性并加入发布门禁。
完成上传/ZIP 资源预算、文件删除语义、Shipyard 清理。
处理 query 凭据和长期缓存风险。
完成标准
每项修复包含可失败的回归测试,不只做输入检查。
P0/P1 安全项使用 Security Advisory 或私有分支协调,修复发布前不公开完整 PoC。
发布门禁覆盖源码、Dashboard、wheel、Docker 使用的同一依赖图。
关闭问题前附验证命令、测试输出和实际发布版本。
审计范围
审计基于
master当前提交d98a29600(v4.26.6),覆盖:本地验证:
uv run ruff check .:通过uv run ruff format --check .:480 files already formatteduv run pytest tests/test_fastapi_v1_dashboard.py tests/test_backup.py tests/test_shipyard_neo_booter.py -q:146 passedcd dashboard && pnpm typecheck:通过cd dashboard && pnpm audit --prod --json:4 low / 35 moderate / 18 high优先级总览
P0:已有公开安全问题
P0-1 多处 SSRF 仍需统一出口策略
P0-2 插件安装链路等价于进程内代码执行
pluginAPI key scope 同时覆盖查看、配置、安装和加载插件,scope 泄漏后可直接进入代码安装路径。system/独立code_installscope 和短期再认证;验证市场签名;逐步把第三方插件移入低权限隔离进程。P0-3 MCP 配置可启动任意本地命令
P1:高风险问题
P1-1 插件页面资源令牌与 Dashboard 会话 JWT 类型混淆
astrbot/dashboard/api/auth.py:145-173、astrbot/dashboard/services/plugin_page_service.py:894-919token_type、aud、iss;资源 token 使用独立签名密钥和独立 decode 函数;require_scope()明确拒绝非 session token;增加“asset token 请求 system endpoint 必须 401/403”的回归测试。P1-2 备份知识库元数据可使写入路径逃逸可信根目录
astrbot/core/backup/importer.py:744-789manifest.json的 ZIP,不能修复此路径问题。.、..;最终目录必须相对可信kb_root_dir;所有安全预检必须在清库和写文件前完成;增加临时目录外写入回归测试。P1-3 Dashboard/文件下载在证书错误后默认关闭 TLS 验证
astrbot/core/utils/io.py:276-344、astrbot/core/utils/io.py:508-600CERT_NONE重试,网络路径攻击者可替换下载内容;ZIP 格式检查不提供来源完整性保证。P1-4 Dashboard 生产依赖存在 18 个 high advisories,CI 不阻断
dashboard/package.json、dashboard/pnpm-lock.yaml、.github/workflows/dashboard_ci.ymldashboard/package.json或dashboard/pnpm-lock.yaml,不能视为依赖修复。pnpm audit --prod --audit-level high门禁;Dependabot 增加/dashboardnpm ecosystem;无法立即升级的项目建立有到期日的精确 allowlist。P1-5 手动 release 可把一个 ref 的源码发布到另一个 tag
.github/workflows/release.yml:7-15,30-51,130-151,210-231workflow_dispatch独立接收ref和tag,未验证 checkout HEAD、tag commit、pyproject.tomlversion 三者一致,可能产生标签、源码、PyPI wheel、Release asset 不一致。HEAD == tag commit且tag == v${project.version};禁止覆盖既有 release asset,除非显式受控重发流程。P1-6 tag 发布未依赖测试、wheel smoke、依赖审计
.github/workflows/release.yml、.github/workflows/docker-image.ymluv build、安装 wheel 后启动 smoke;验证通过后才允许 PyPI、GitHub Release、R2 和 Docker push。P1-7 Python/Node 发布依赖不可复现
.gitignore:6、scripts/run_pytests_ci.sh:18-20、.github/workflows/docker-image.yml:47-63,161-171、scripts/hatch_build.py:47-62uv.lock未跟踪;Docker/Hatch 使用npm install,绕过唯一提交的pnpm-lock.yaml。uv.lock;CI 用uv sync --frozen --group dev;Docker/export 禁止构建时重新 lock;所有 Dashboard 构建统一固定 pnpm 并使用pnpm install --frozen-lockfile;package.json声明packageManager。P2:稳定性与资源耗尽
P2-1 备份上传/导入缺少统一资源预算
astrbot/dashboard/services/backup_service.py、astrbot/core/backup/importer.pyread()可造成内存或磁盘耗尽。P2-2 文件 DELETE 接口返回成功但不删除,上传无配额
astrbot/dashboard/api/files.py:70-111、astrbot/dashboard/services/chat_service.py:589-637DELETE /api/v1/files/{attachment_id}仅回显 ID;文件和 DB 记录保留。filescope 可持续上传且无文件/主体/全局配额。P2-3 Shipyard Neo 启动异常会泄漏 client/远端 sandbox
astrbot/core/computer/booters/shipyard_neo.py:396-463try/except BaseException包围;异常时先删除 sandbox,再关闭 client,清空组件字段,最后原样抛出;取消清理考虑asyncio.shield();增加 refresh 异常和 cancellation 测试。P2-4 Docker 手动 release tag 获取参数拼写错误
.github/workflows/docker-image.yml:22-27,127-142fetch-tag: true不是actions/checkout支持参数;配合fetch-depth: 1,手动流程中的git describe --tags不可靠。fetch-tags: true和fetch-depth: 0;随后验证 checkout HEAD 与解析 tag commit 一致。P3:长期风险
P3-1 API key/JWT 支持 URL query 认证
astrbot/dashboard/api/auth.py:44-55、Open API/Live Chat WebSocket 认证路径Authorization/X-API-Key;WebSocket 通过认证 HTTP endpoint 换取一次性短期 ticket;统一日志脱敏。P3-2 QQ Official 会话缓存无 TTL/容量限制
astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py现有 PR Review 结论
建议执行顺序
完成标准