
我们从内部审查了这个作品集的安全:聊天、消息 API、服务器和 15 个概念演示站。共发现 8 个问题,其中包括聊天所在源上的脚本注入,已全部修复。
概述
这个网站不只是静态页面。它运行着基于 VITON ID(Firebase Auth 与 Firestore)的聊天、一个保存联系表单消息并发送邮件的小型 Node API、Docker 中的 nginx 服务器,以及 /demos/ 下 15 个概念网站的副本。2026 年 9 月 28 日,我们从内部审查了全部内容:代码、Firestore 规则、服务器与容器配置以及 npm 依赖。
对每个部分,我们都从攻击者的角度提问:外部的人能用它做什么,会让站点所有者付出什么代价?只有复现成功的问题才算作发现,每项修复在发布前都在生产配置的本地副本上重新测试。
8
项安全发现,全部修复
来源:代码审查,2026 年 9 月 28 日
1
项高危问题:聊天所在源上的脚本注入,已关闭
来源:在本地副本上复现修复前后
119
个演示页面在新安全策略下加载,零违规
来源:无头 Chrome 检查,2026 年 9 月 28 日
0
个网站与 API npm 依赖中的已知漏洞
来源:npm audit,2026 年 9 月 28 日
思路
我们逐一阅读了每个 API 路由、令牌校验、Firestore 规则及其 39 项模拟器测试、nginx 与 Docker Compose 配置,以及全部 15 个演示站的代码。我们没有对线上服务器进行探测,而是在本地运行相同的容器(nginx 以及使用生产配置的 API),在那里尝试每一种攻击。
最严重的问题出现在演示站中,而不是网站本身。Oriva 目录页把地址参数 ?cat= 作为 HTML 插入页面,因此一个精心构造的链接就能在 tarasovvitalii.com 上执行脚本——而聊天正是在这个源上保存 Firebase 会话。所有者点击一次,就可能交出整个收件箱。其余 14 个演示站只会把地址参数与已知值比较。
修复内容:演示站只接受已知的分类和排序;/demos/ 拥有独立的内容安全策略(CSP);Leaflet 用完整性哈希固定;/demos/<id> 的重定向按严格模式生成;拒绝可能向 mailto: 链接夹带字段的地址;全局每日上限保护存储;API 以非特权用户在只读文件系统上运行;隐藏 nginx 版本,HSTS 覆盖 www。
图集
成果
8 项发现,8 项已修复:高危 1 项、中危 1 项、低危 6 项。在旧演示代码上会执行的载荷在新代码上不再起作用,过去会注入 Set-Cookie 头的请求现在只得到普通的 404。全部 119 个演示页面在新策略下加载,零违规;API 测试 48 项全部通过,并覆盖了新规则;npm audit 在网站与 API 的依赖中未发现已知漏洞。
经检查确认可靠的部分:Firebase ID 令牌校验(仅 RS256、必须带密钥 ID,并校验受众、签发者和有效期)、Firestore 规则(任何人都无法读取他人的对话或以所有者身份写入)、邮件模板(所有值均已转义,无头部注入)、日志(不含令牌、邮箱或 IP 地址)以及聊天界面(访客文本从不以 HTML 插入)。
安全审计
以下每项发现都先复现再计入,修复后又在生产容器的本地副本上重新测试。按风险等级排序。
-
高
概念演示站中的脚本注入,位于聊天所在的源
已修复之前
Oriva 目录页把地址参数 ?cat= 作为 HTML 插入页面。构造的链接会在 tarasovvitalii.com 上执行脚本,而聊天在此保存 Firebase 会话:所有者点击一次就可能暴露收件箱和所有者账户。
之后
只接受已知的分类和排序值。同样的载荷不再执行,其余 14 个演示站也已检查过同类问题。
-
中
演示站缺少安全策略,第三方脚本无完整性校验
已修复之前
52 个演示页面从 unpkg.com 加载 Leaflet 时没有完整性哈希,/demos/ 也不发送内容安全策略:被攻破的 CDN 或任何注入脚本都能触及整个源。
之后
Leaflet 用 SRI 哈希固定,/demos/ 拥有独立策略:请求只能发往本站,脚本只能来自本站和已固定的文件,禁止插件。119 个页面,零违规。
-
低
服务器重定向中的响应头注入
已修复之前
从 /demos/<id> 到 /demos/<id>/ 的重定向会原样回写解码后的路径,因此链接中的 %0d%0a 会在响应里写入额外的头,例如 Set-Cookie。
之后
重定向只接受字母、数字、连字符和下划线,并自行构建地址。同一请求现在只得到普通的 404。
-
低
所有者“回复”链接中的隐藏字段
已修复之前
类似 me@x.com?bcc=…&body=… 的地址能通过校验,于是所有者收件箱和邮件中的“回复”链接会预填隐藏的密送和正文。名字中还可能带有改变文字方向、用于伪装内容的字符。
之后
拒绝含 URL 分隔符的地址,mailto: 链接中的地址经过编码,并删除方向控制字符。三种情况都有新的 API 测试覆盖。
-
低
已存储消息没有总量上限
已修复之前
限制只按 IP 地址计算。轮换地址就能不断添加表单和机器人提交,直到磁盘写满。
之后
在按 IP 的限制之上,增加了已存储提交的全局每日上限(默认 500)。超过后表单会提示“请稍后再试”。
-
低
消息 API 以 root 身份运行
已修复之前
API 容器以 root 身份运行,文件系统可写,并保留全部默认 Linux 能力:其中任何漏洞都会给攻击者一个方便的立足点。
之后
改为以非特权用户 node 在只读文件系统上运行,移除全部 Linux 能力并禁止提权。
-
低
暴露服务器版本,nginx 分支过时
已修复之前
每个响应都带有“server: nginx/1.27.5”,网站容器使用的 1.27 分支已不再获得修复。
之后
所有响应都隐藏版本号,容器改用当前稳定的 nginx 分支。
-
低
强制 HTTPS 未覆盖 www
已修复之前
告诉浏览器只使用 HTTPS 的 HSTS 头只在主域名发送,www 上没有,也不覆盖子域名。
之后
www 同样发送 HSTS,策略也包含子域名,因此 http://www… 也会升级到 HTTPS。
本案例不能证明的
这是我们自己的网站,不是客户项目。审查由我们基于源代码完成,并非第三方渗透测试或认证。攻击是在生产容器的本地副本上复现的,而非针对线上服务器。
结论仅适用于 2026 年 9 月 28 日所检查的内容:新代码、新依赖或新演示站都需要同样的审查。演示站仍与网站共用同一个源。新策略限制了注入代码能触及的范围;将演示站迁移到独立域名才能彻底隔离。
在筹划类似的项目?每条消息都由我们的创始人 Tarasov Vitalii 亲自阅读。
在 VITON13 Studio 预订类似项目
下一个项目
Möbius School & Institute带个人账户的中小学与大学网站
概念2026
全部作品 (32)
