You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[安全] LLM API Key 明文存储,且 base_url 可控(密钥泄露 / SSRF) #18
Activity
wen1112 commentedon Jul 6, 2026
@jackhu3301 @wyzBelinda
FenjuFu commentedon Jul 21, 2026
读了下相关代码,先补两条核实结果,再提方案。#15 / #17 我已经提了 PR(#29 / #30),这个想先对齐再动手。
核实
api/settings.py的LLMSettingsResponse字段里没有api_key,base_url会返回但 key 不会。所以现在的暴露面是落库明文,不是接口泄露。这点值得写进回归测试固定住,否则以后有人给响应模型加字段就破功了。customprovider 的base_url走Field(None, max_length=500),除长度外无任何校验,LLMClient直接拿它发出站请求 —— SSRF 面确认存在。方案(三个决策点想请你们拍板)
A. 加密方式
倾向 Fernet + 主密钥从环境变量注入(
cryptography已是常见依赖),而不是直接上 KMS:本项目定位是可自托管的本地系统,强依赖云 KMS 会抬高部署门槛(和 #6「降低部署门槛」相冲)。具体做法:
LLM_SETTINGS_ENCRYPTION_KEY环境变量提供主密钥,缺失时启动即失败而不是降级明文(fail closed)。api_key_encrypted,避免和历史明文列混淆。LLMClient构造时解密,不进日志、不进响应模型。想确认的:能否接受「必须配置一个环境变量才能启动」这个硬性要求?如果希望单机 demo 免配置,我可以做成「未配置时自动生成密钥文件到 data/ 并 chmod 600」,但那样安全性会打折,我个人不推荐。
B. 存量数据迁移
仓库已有 alembic(
alembic/versions/0af50254bf91_add_skill_configs_table.py),所以我打算写一个 migration:新增api_key_encrypted列 → 读旧明文列逐行加密写入 → 清空旧列。想确认的:是直接删除旧
api_key列,还是保留一个空列过渡一个版本?删掉更干净,但如果有人已经在生产跑了、又没备份,回滚会丢配置。C. SSRF 白名单的粒度
三种做法,请选:
LLM_ALLOWED_BASE_URLS环境变量列出允许的 host,不在其中一律拒。最稳,但自托管用户每换一个模型服务就要改配置。customprovider,只保留内置 provider 列表。最安全,但会砍掉「接任意 OpenAI 兼容端点」的能力 —— 考虑到modules/pixi_RAG-HPO那边就是靠RAG_HPO_BASE_URL接 DeepSeek/Groq 的,这个能力应该是有人在用的,所以我倾向 2,把安全边界交给部署者显式声明。方向定了我就按这个做,加密/迁移/白名单可以拆成两个 PR(加密+迁移一个,SSRF 一个),方便分开审。也完全 OK 由你们自己来做 —— 那我就不动,只把上面的核实结果留在这。