7.6 KiB
7.6 KiB
VideoRoll 项目审计报告
需要立即修复 (Critical)
1. Fernet 密钥管理缺失
- 文件:
src/videoroll/utils/fernet.py - 密钥文件不存在时自动生成新密钥,无备份/轮转机制
- 密钥丢失 = 所有加密的 YouTube cookies、Bilibili tokens、OpenAI API keys 永久不可恢复
- 无密钥轮转支持,
@lru_cache使密钥在进程生命周期内无法刷新 - 改进: 启动时检查密钥是否存在,不存在则报错退出而非静默生成;支持密钥轮转
2. 登录接口无防暴力破解
- 文件:
src/videoroll/apps/orchestrator_api/main.py(/auth/login) - 无速率限制,可无限次尝试密码
- PBKDF2 200k 迭代提供了一定的单次计算成本,但不足以作为唯一防线
- 改进: 加入
slowapi或类似限流库,限制同一 IP 的登录尝试频率
3. Remote API token 通过 query 参数传递
- 文件:
src/videoroll/apps/orchestrator_api/remote_api_settings_store.py ?token=出现在 access log、代理日志、浏览器历史、Referer header 中- token 虽然在存储时做了 PBKDF2 hash,但传输过程中明文暴露
- 改进: 改用
Authorization: Bearerheader 传递 token
高优先级 (High)
4. orchestrator_api/main.py 是 God File
- 文件:
src/videoroll/apps/orchestrator_api/main.py(2900+ 行) - 80+ 路由、CORS 配置、认证中间件、后台线程(清理、YouTube 扫描)全部在一个文件中
- 错误处理不统一:有的直接
raise HTTPException,有的try/except httpx.HTTPError,有的except Exception: pass _ingest_youtube_source在多处被调用,但内部自行创建httpx.Client和SessionLocal,无法参与外部事务- 改进: 按职责拆分为独立 router 模块(auth、tasks、settings、youtube、maintenance);统一错误处理中间件
5. Celery worker 无重试和确认机制
- 文件:
src/videoroll/apps/subtitle_service/worker.py process_job、process_render_job、task_queue_tick均未使用autoretry_for、retry()、acks_late- worker 被 OOM/SIGKILL 杀掉后任务直接丢失,仅有的恢复逻辑
_recover_interrupted_subtitle_jobs()将任务标记为 FAILED 而非重试 - 翻译重试使用
while True+time.sleep()阻塞 worker 线程 - 改进: 加
acks_late=True+autoretry_for或手动retry();翻译重试改用 Celery 内置 retry 机制
6. 容器以 root 运行
- 文件:
Dockerfile - 无
USER指令,容器进程以 root 身份运行 - 应用被攻破后攻击者拥有完整 root 权限
- 改进: 加
RUN useradd -r -s /usr/sbin/nologin videoroll和USER videoroll
7. 内部服务间认证 token 从 S3 secret 派生
- 文件:
src/videoroll/utils/internal_api_token.py - token =
SHA256("videoroll-internal-token:v1:" + s3_secret_access_key) - S3 secret 轮转后所有内部认证同时失效,无独立的内部密钥配置
- 无 HMAC、无 per-service nonce、无过期机制
- 改进: 独立的
INTERNAL_API_SECRET环境变量,不与 S3 secret 绑定
8. 安全相关 cookie 配置问题
- 文件:
src/videoroll/apps/orchestrator_api/main.py - 设备 cookie 有效期 180 天,无会话撤销机制,被盗 cookie 可用半年
- 非 HTTPS 时不设
Secure标志,cookie 以明文传输 allow_methods=["*"]+allow_credentials=True配置过于宽松- 密码 hash 缓存在 app.state 中,改密码后旧 hash 不会立即失效
- 改进: 缩短 cookie 有效期;始终设
Secure;限制 CORS methods/headers;密码变更时清理缓存
中优先级 (Medium)
9. Auto-migration 功能受限
- 文件:
src/videoroll/db/auto_migrate.py - 只能
ALTER TABLE ADD COLUMN,无法处理:重命名列、改类型、建新表、加约束/索引、删列、数据迁移 @lru_cache使 rolling deploy 时旧进程不会执行新 migration_add_column使用字符串拼接构造 SQL,虽然当前是硬编码值但存在注入隐患- 改进: 如果 schema 变更频繁,考虑引入 Alembic;至少将 SQL 构造改为参数化
10. 代码重复
_effective_youtube_settings在orchestrator_api/main.py和subtitle_service/worker.py中重复_read_s3_bytes在两个文件中几乎完全相同_safe_append_log_line、_safe_append_log_block、_cleanup_local_work_root等辅助函数仅存在于 worker.py 但其他模块也需要- 改进: 提取到
videoroll/utils/共享模块
11. Docker entrypoint 单点故障
- 文件:
docker/entrypoint.sh - 三个进程并行运行(uvicorn + 2 celery workers),一个挂了整个容器退出,无重启逻辑
- 没有
exec启动 uvicorn,SIGTERM 发给 bash 而非 uvicorn,信号处理可能异常 - 无健康检查 / readiness probe
- 改进: 考虑用 supervisord 或拆分为独立容器;对 uvicorn 使用
exec
12. 前端类型安全弱
- 文件:
src/web/src/lib/types.ts,src/web/src/lib/http.ts Asset.kind、SubtitleJob.status、PublishJob.state用string而非联合类型fetchJson做as T强转,无运行时校验,API 响应变化时静默产生错误数据- 部分页面用
alert()/confirm()做用户反馈 - 改进: 将已知枚举定义为 union types;关键 API 响应加 zod 运行时校验
13. 依赖版本只有下限没有上限
- 文件:
pyproject.toml cryptography>=42.0.0、fastapi>=0.115.0、yt-dlp>=2026.2.4等均无上界- 未来
pip install可能拉入不兼容或有安全问题的版本 - 改进: 对安全敏感的包(cryptography、sqlalchemy、psycopg)加
<next_major上界
14. 大量错误被静默吞掉
- 散布在
orchestrator_api/main.py和subtitle_service/worker.py中的except Exception: pass - cookie 文件处理、S3 操作等关键路径中的异常被忽略,生产环境排查困难
- 改进: 至少加
logger.warning()记录被吞掉的异常;关键路径不吞异常
15. S3_USE_SSL 默认关闭
- 文件:
src/videoroll/config.py s3_use_ssl: bool = Field(False, ...)导致默认情况下数据在网络上明文传输- 改进: 生产环境默认
True,仅在开发配置中显式关闭
低优先级 (Low)
16. 测试覆盖不足
- 纯函数(
publish_meta_rules、publish_review)测试质量好 - 缺少:API 层集成测试、Celery 任务测试、auth 中间件测试、错误路径测试
test_translate_resume.py手动构造假httpx模块,脆弱易碎- 改进: 补充 API endpoint 测试(用
TestClient);增加 Celery 任务的单元测试
17. lru_cache 导致测试间状态泄漏
get_orchestrator_settings()等被@lru_cache住,测试间无法重置配置- 改进: 提供
clear_settings_cache()辅助函数,或在测试中使用@pytest.fixture管理 cache
18. 硬编码超时和魔法数字
_TASK_QUEUE_LOCK_TTL = 300、_TASK_QUEUE_HEARTBEAT_INTERVAL_SECONDS = 30等散布在代码中- 环境变量解析
int(value)无校验,非法值会在导入时崩溃 - 改进: 将可配置值移入 pydantic Settings;加
Field(gt=0)校验
19. Dockerfile 安装了不必要的系统包
pciutils、clinfo、Intel GPU 驱动无条件安装,增加镜像体积和攻击面- 改进: 将 Intel GPU 相关包改为可选的 build arg 控制
20. 密码复杂度要求过低
- 文件:
src/videoroll/apps/orchestrator_api/admin_auth_store.py validate_new_password()仅检查长度 8-128 字符,无复杂度要求- 改进: 加入基本复杂度校验(大小写+数字+特殊字符)或常见密码检查