- 审计日期:2026-03-22(Asia/Shanghai)
- 审计对象:
- 线上站点:
https://blog.ericterminal.com/ - 源码目录:
/Users/Eric/Dev/TypeScript/cf-astro-blog
- 线上站点:
- 审计方式:
- 黑盒检测(HTTP 头、公开接口、访问控制、基础攻击面)
- 白盒审计(认证授权、输入校验、SSRF、XSS、依赖风险、限流策略)
- 依赖漏洞扫描(
npm audit --omit=dev --registry=https://registry.npmjs.org --json)
- 已完成修复:F-01(头像代理 SSRF/SVG)、F-02(依赖漏洞)、F-03(公开 AI 同源校验与
/chat人机校验)、F-04(JWT 密钥强度校验)。 - 风险接受:
/ai/terminal-404当前不启用 Turnstile,依赖同源校验 + IP 限流控制成本与滥用面。 - 已验证:
npm audit --omit=dev --registry=https://registry.npmjs.org输出found 0 vulnerabilities。 - 待选优化:F-05(健康检查最小化)可按运维需求决定是否收敛。
整体安全基线较好(后台鉴权、CSRF、防护头、Markdown 安全渲染均到位),但存在 1 个高优先级问题 和 若干中低优先级风险,建议先修复头像代理相关问题,再处理依赖升级与公开 AI 端点风控。
- 高风险:1
- 中风险:2
- 低风险:2
- 位置:
src/admin/routes/friend-links.ts- 目标校验:
validateAvatarTarget(第 105-126 行) - 拉取实现:
fetch(..., { redirect: "follow" })(第 313-321 行) - 类型放行:
content-type仅判断startsWith("image/")(第 327-334 行)
- 目标校验:
- 初始 URL 会做私网/本地校验,但 重定向链路未逐跳复验(
redirect: "follow"),可被“外网地址 -> 内网地址”重定向绕过策略。 - 仅按
hostname字符串判断是否私网,未进行解析后 IP 复验,存在 DNS Rebinding 风险面。 - 代理接口接受并回传
image/svg+xml,在同源上下文中若被直接访问/嵌入不当,可能扩展为脚本执行载体。
- 直接私网地址会被拦截(符合预期):
GET /api/friend-links/avatar?url=http://127.0.0.1/->400 头像地址不允许使用本地或内网主机
- 通过外站重定向到私网时未在业务层拦截(返回 502 而非 400 拦截):
GET /api/friend-links/avatar?url=https://httpbin.org/redirect-to?url=http://127.0.0.1/->502 头像暂时不可用
- SVG 可被代理返回:
GET /api/friend-links/avatar?url=https://raw.githubusercontent.com/simple-icons/simple-icons/develop/icons/github.svg- 返回
200且content-type: image/svg+xml
- 改为
redirect: "manual",每一跳Location都重新执行validateAvatarTarget。 - 新增“解析后 IP 校验”与“最终连接地址校验”(防 DNS Rebinding)。
- 头像代理白名单建议仅允许
image/jpeg|png|webp|avif|gif,禁用 SVG;如必须支持 SVG,需做净化与下载头隔离(例如强制Content-Disposition: attachment)。
执行命令:
npm audit --omit=dev --registry=https://registry.npmjs.org --json结果摘要:
- 总计:7 个漏洞(高危 4 / 中危 3)
- 重点包:
hono(直接依赖,当前^4.11.6,建议升级到>=4.12.7)@astrojs/cloudflare链路涉及wrangler/miniflare/undici(含高危公告)h3、devalue(传递依赖)
部分漏洞在开发链路/构建链路中触发,部分与运行时框架组件相关。即使短期不可直接利用,也会提升整体供应链与维护风险。
- 升级
hono至安全版本。 - 升级
@astrojs/cloudflare与wrangler到已修复区间。 - 升级后重新执行
npm audit+ 回归测试,确认无新破坏。
- 位置:
src/admin/routes/public-ai.tsisSameOriginRequest对缺失Origin的请求直接放行(第 123-127 行)/terminal-404未启用 Turnstile(第 546-553 行,requireTurnstile: false)- 限流计数为 KV 的
get + put非原子更新(第 339-350 行)
- 黑盒验证表明命令行可直接调用
/api/ai/terminal-404并得到 200 返回。 - 已有限流,但并发场景下非原子计数存在误差;攻击者通过 IP 轮换仍可放大调用成本。
- 终端接口也启用人机校验,或追加签名令牌/一次性挑战。
Origin缺失默认不放行(仅对白名单场景放行)。- 限流迁移到原子计数方案(Durable Object/专用限流服务/D1 原子事务计数)。
- 位置:
src/admin/middleware/auth.tsgetJwtSecret直接接受任意字符串(第 61-63 行)createToken/verifyToken直接使用env.JWT_SECRET(第 155-180 行)
若部署时误配置为空或弱密钥,可能导致会话令牌可伪造风险上升。
- 启动时强制校验密钥长度与熵(例如最少 32 字节随机值),不满足则拒绝启动。
- 位置:
GET /api/health - 当前返回
status + timestamp。
- 若无外部依赖该字段,可仅返回静态健康状态,减少可观测信息。
- 安全响应头较完整:CSP、X-Frame-Options、Referrer-Policy、Permissions-Policy、COOP、HSTS(线上由 Cloudflare 注入)均已生效。
- 后台会话 Cookie 设置合理:
HttpOnly + Secure + SameSite=Strict。 - 后台关键写操作普遍启用 CSRF 校验。
- Webmention 路由对重定向链路有逐跳校验,且能拦截跳转到私网地址。
- Markdown 渲染器对原始 HTML、危险协议链接有防护。
- 未发现源码/配置文件直接暴露(
.git、package.json、.dev.vars等线上均 404)。
- P0:先修头像代理 SSRF/SVG 问题(F-01)
- P1:依赖升级 + 公开 AI 接口风控增强(F-02, F-03)
- P2/P3:配置强校验与信息最小化(F-04, F-05)
- 本次审计以“源码 + 线上 HTTP 行为”为主,未包含侵入式漏洞利用(如后台凭证验证、真实内网探测、社会工程等)。
- 若你希望,我可以下一步直接按 P0/P1 给出最小改动补丁并附带回归测试。