Files
pigway-frame-flow/docs/audits/2026-10-05-project-audit.md

84 lines
4.7 KiB
Markdown
Raw Permalink 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.
# Frame Flow 项目审计 — 2026-10-05
审计基线:794a7e1485cc9046be3e77f6557c75740305ac47。
范围:本地源码、配置、Mock 测试与依赖审计;不包含本次 NAS 状态验证、真实账号登录或真实设备写入。未修改业务代码。
## 发现
### P1:队列扫描上限导致后续高优先级告警饥饿
`display/service.py:222` 只取按创建时间排序的前 50 个 QUEUED 操作,再跳过
被 override 阻挡的低优先级请求。如果这 50 项全被阻挡,第 51 项更高优先级
告警每一轮都无法被扫描到;其他设备请求与本地渲染也可能受影响。
Mock 复现:激活 priority=50 的一小时 override,排入 50 个 priority=10
请求,再排 priority=90 请求,调用 process_one 后后者仍为 QUEUED。
建议先筛选可执行请求,或分页扫描直到找到可执行操作;增加跨设备与优先级回归测试。
### P2:会话失效未更新连接状态,并误清第一方登录
`integrations/kokonna_official/rpc.py:44-51` 在官方返回“请重新登陆”时抛出
UNAUTHORIZED,但没有使官方 session 失效。`connection.py:104-113` 只依据
本地 token 非空,继续显示 authorized=true。`web/app.js:17` 将任意 API 401
都当作 Frame Flow 登录失效并执行 forgetLogin,包括外部官方会话过期。
Mock 复现:RPC 返回 HTTP 500 / error -1 / 请重新登陆后,authorized 仍 true。
建议区分第一方认证与外部账号过期,持久化失效状态,保留 Frame Flow 登录,
在官方区域提供重新连接提示。
### P2:损坏的可选官方会话文件阻止整个服务启动
`connection.py:44-51` 在构造函数中直接解析 JSON 并索引字段,没有异常隔离。
DeviceRegistry 在应用启动时构建该对象。损坏 JSON、缺字段或文件不可读会
使可选功能故障升级为全服务启动失败,影响 API Key、UI 和 Scheduler。
Mock 复现:官方 secret 文件内容为 `{broken`,create_app 抛 JSONDecodeError。
建议隔离并禁用该连接,记录不含文件内容的诊断;其他核心功能继续启动。
### P2:持久化失败导致断开状态与重启状态不同
`connection.py:122-127,146-157` 先修改内存,再保存。磁盘满、权限错误等
导致保存失败时没有回滚。尤其 disconnect 已清内存,而磁盘仍保留旧 token,
重启后又恢复旧连接;虽然原请求返回错误,随后状态查询却会显示未连接。
Mock 复现:让 _save 抛 OSError;当前 authorized=false,重新构造连接后 true。
建议先原子持久化候选状态,再提交内存状态;失败时保持一致并提供明确错误。
### P2:Request ID 脱敏遗漏官方会话
`api/app.py:148-150` 仅检查 API Key、Frame Flow Token、registry.keys,
没有检查用于官方会话的 settings.additional_secrets。符合 Request ID 长度和
字符限制的会话值若被客户端误用为 X-Request-ID,可被响应头和错误模型原样回显。
本问题不表示未授权者能凭空取到 token,而是违反已有 secret 不回显约束。
Mock 复现:完成模拟官方连接后,将 synthetic session `mock-session` 作为
X-Request-ID 发给 /health,响应原样返回该值。建议统一使用完整 secret 集合。
## 验证
- pytest:154 passed,0 failed,0 warning。
- Ruff:通过(应用和 tests)。
- mypy:36 个源码文件通过。
- pip-audit(requirements.lock):No known vulnerabilities found。
- 五项专项 Mock 复现均确认上述行为,不调用真实 KoKonna。
- 没有因发现问题而启用官方写方法;严格 RPC allowlist 仍阻止未启用方法。
## 边界与下一步
测试全绿不代表无缺陷:现有套件没有覆盖以上失败场景。
本轮没有修复或部署;建议先修复队列饥饿,再统一外部账号状态与第一方认证,
然后补齐会话文件容错、持久化事务一致性和 Request ID 脱敏测试。
依赖审计仅表示本次查询未发现已知漏洞,不是全部依赖安全的证明。
## 修复与复验
上述五项已修复:队列使用 keyset 分页查找可执行操作;官方账号失效使用
独立 `OFFICIAL_AUTH_REQUIRED` 错误码并清除会话,前端保留第一方登录且提供
重新连接入口;可选 secret 解析失败不再阻止核心启动;持久化候选状态成功后
才提交内存变更;Request ID 检查涵盖官方会话凭据。
复验:164 passed、0 warning(新增 10 项回归测试);Ruff 通过;mypy 36 文件
通过;113 项布局检查通过;官方过期/第一方登录隔离浏览器检查通过。
已知本地凭据对照历史扫描通过(278 个 blob);该扫描不等同于发现所有未知
secret 的通用审计。本轮不部署 NAS,不执行真实设备写接口。