8.8 KiB
ephron.ren 安全审计总 PRD(2026-05-16 汇总版)
文档目的
本 PRD 汇总 2026-05-16 对 ephron.ren 进行的多轮安全审计结果,统一记录:
- 已确认安全基线
- 已确认漏洞 / 缺陷
- 已排除或降级的候选问题
- 配置风险与后续修复优先级
本文件用于替代分散的 round2 / round3 阶段记录,作为当前单一汇总版本。
一、审计范围
本轮覆盖以下服务与共享模块:
authblogcanvashomepromptshared
审计方式:
- 全仓静态源码审计
- 非破坏性线上动态验证
- 仅进行低风险、只读或受控请求验证
二、总体结论
当前总体判断
ephron.ren 不是裸奔状态,具备较明确的基础安全基线:
- 服务端 admin 鉴权存在
- 权限检查存在
- 统一安全响应头在线上已生效
- 大部分 admin 写操作具备 CSRF 防护
- service token 与 admin 边界总体存在
- blog 图片上传链具备权限、CSRF、大小限制和重编码处理
- auth 登录跳转链具备 redirect 校验
但本次审计也确认了数个真实问题,主要集中在:
prompthome admin
当前最准确结论仍然是:
项目具备安全基线,但不能认定为“已经安全完成”;已确认若干需尽快修复的问题。
三、已确认安全基线
1. 路由守卫结论
- 未发现前端 SPA 式客户端路由守卫
- 未发现
router.beforeEach、createRouter、react-router、middleware.ts等典型模式
- 未发现
- 存在服务端 admin 路由级鉴权/重定向
- 各服务 admin 入口会读取
ephron_authCookie - 校验登录态与权限
- 未登录时重定向到
auth.ephron.ren/login
- 各服务 admin 入口会读取
2. 统一安全头在线上已确认生效
线上已确认以下响应头存在:
Content-Security-PolicyX-Frame-OptionsX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-origin
典型 CSP 现状包含:
frame-ancestors 'none'base-uri 'self'form-action 'self' https://*.ephron.ren
3. CSRF 基线存在
shared/csrf.py 已实现双提交 cookie 风格 CSRF:
- GET 生成 token
- 表单与 Cookie 同时携带 token
- POST 校验一致性
- token 有时效限制
- 使用安全比较
4. service token / admin 权限边界存在
例如 home admin 已明确拒绝 service token:
- 返回
403 - 错误信息:
Service tokens cannot access home admin
5. blog Markdown 正文链存在白名单净化
blog/src/utils/markdown.py 中:
- Markdown 渲染后经过
bleach.clean(...) - 属于白名单净化,而不是裸渲染 HTML
6. blog 图片上传链具备基础防护
当前已确认:
- 登录权限检查
blog.asset.upload权限控制- CSRF 校验
- 文件大小限制
- Pillow 解码后重编码为 WebP
- 写入固定上传目录
四、已确认问题
1. 高危:prompt /api/test-connection 匿名 SSRF / 外连探测面
结论
高危,已确认。
源码证据
prompt/src/routes/api.py
- 存在公开
POST /api/test-connection - 直接接受:
providerbase_urlapi_keymodel
- 服务端直接对
{payload.base_url}/chat/completions发请求 - 未见登录校验、权限校验、CSRF 限制
线上验证
已非破坏性验证:
POST https://prompt.ephron.ren/api/test-connection- 使用
base_url=http://127.0.0.1:9 - 返回:
200 - 响应:
{"success":false,"error":"All connection attempts failed"}
这表明:
- 接口匿名可访问
- 服务端确实尝试连接指定地址
- 可被用于网络探测 / SSRF 探针
影响
- 探测内网 / 本机 / 特定外部地址
- 回显网络结果差异
- 若未来可访问内部控制面或 metadata 地址,风险进一步升级
建议
- 该接口至少改为管理员鉴权
base_url做严格白名单- 禁止 localhost / 内网 / link-local / metadata 地址
- 禁止透传详细网络错误
- 增强审计日志与限流
2. 中危:prompt 调试测试链潜在 HTML 注入 / XSS
结论
中危,已确认存在危险链路。
源码证据
prompt/static/js/test-prompt.js
- 错误事件:
contentDiv.innerHTML = <div class="error">${event.detail}</div>
- 普通异常:
contentDiv.innerHTML = <div class="error">${error.message}</div>
- 流式内容:
contentDiv.innerHTML = this.renderMarkdown(fullContent)renderMarkdown()调用marked.parse(text)
prompt/src/services/llm.py / prompt/src/routes/api.py
- 上游错误文本 / 响应文本可进入错误回显链
影响
- 管理员面自触发 / 调试型 XSS
- 若错误页或上游响应可控,可能进一步形成可利用注入
- 结合 CSP 中保留
'unsafe-inline',利用门槛下降
建议
- 错误展示改用
textContent - markdown 输出增加 sanitize
- 后端不要透传原始
response.text - 仅允许可信渲染链处理富文本
3. 中危:prompt 登录态写接口缺 CSRF
结论
中危,静态确认。
源码证据
prompt/src/routes/api.py 中以下接口依赖登录态,但未见 verify_csrf_token(...):
/api/prompts/{key}/test/api/prompts/{key}/test/save-example
其中:
/test是调试触发接口/test/save-example是明确的状态变更接口
线上验证
匿名访问会被 401 拦截,说明依赖 cookie 登录态。当前未使用真实登录态做利用验证,因此认定为静态确认缺陷。
影响
- 登录用户可能被跨站诱导发起请求
/test/save-example可被用于跨站状态变更
建议
- 给所有 cookie 登录态写接口统一补 CSRF
- 抽成共用依赖,避免再漏
- 补自动化测试
4. 中危:home admin 编辑器存在存储型 / 自触发型 DOM XSS
结论
中危,已确认。
服务端证据
home/src/routes/admin.py
- 把数据库内容
json.dumps(content, ensure_ascii=False)注入模板变量content_json
home/src/services/content.py
save_draft(content, uid)/publish_content(content, uid)- 将内容 JSON 原样入库
- 未做字段级 HTML 清洗
前端证据
home/templates/admin/index.html
const initialContent = JSON.parse({{ content_json | tojson }});- 之后多处:
list.innerHTML += ... value="${exp.title}" ...value="${proj.title}"textarea ...>${proj.bullets.join('\n')}</textarea>value="${skill.category}"
- 即数据库内容进入 HTML 片段和属性值拼接
- 未见可靠转义层
影响
- 管理员打开编辑页即可触发 DOM XSS
- 可劫持后台操作上下文
- 可成为管理员面存储型 XSS
建议
- 禁止不可信数据进入
innerHTML += - 改为
createElement/.value/.textContent - 为含引号 / 闭合标签 / 事件属性 payload 补回归测试
五、已复核但不应误报的点
1. 开放重定向未确认成立
auth 登录跳转链调用了 validate_redirect(),因此本轮未确认 auth 存在开放重定向漏洞。
2. canvas /raw/{slug} 当前不作为确认漏洞
源码显示:
X-Frame-Options: SAMEORIGIN- raw 专用 CSP:
frame-ancestors 'self' - 用于受限 iframe 预览
当前证据不足以确认实际越界利用。
3. blog 正文链当前不报直接存储型 XSS
因为存在 bleach.clean(...) 白名单净化。
4. blog 图片上传当前未见明显任意文件上传
当前证据支持其具备基础处理链保护。
六、配置风险与需持续关注项
1. 多服务默认 development 行为是配置陷阱
多服务存在:
IS_DEVELOPMENT = os.getenv("ENVIRONMENT", "development") == "development"docs_url="/docs" if IS_DEVELOPMENT else Noneerror_message = str(exc) if IS_DEVELOPMENT else None
这意味着:
- 若部署漏设
ENVIRONMENT - 服务会默认按 development 行为运行
- 可能意外暴露
/docs - 可能在 500 页面回显错误细节
判断
这是高优先级配置风险,但当前不是已确认线上漏洞。
建议
- 默认值改为 production
- 显式校验环境变量枚举值
- 启动时拒绝未声明环境的生产部署
七、优先级排序
P0
- 下线或严格鉴权
prompt /api/test-connection - 修复
home admin的innerHTML +=注入链
P1
- 修复
prompt调试链 XSS - 为
prompt登录态写接口补 CSRF
P2
- 将多服务
ENVIRONMENT默认值改为 production - 补自动化回归测试
八、最终结论
如果只问“这个项目有没有安全基线”,答案是:有。
如果问“这个项目现在能不能直接认定为安全”,答案是:不能。
本次审计完成后,更准确的说法是:
ephron.ren已具备基础安全防护,但仍存在若干已确认真实问题,尤其集中在prompt与home admin,需要进入修复与回归验证阶段。