4.7 KiB
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,不执行真实设备写接口。