FlintHub assets 静态安全审计报告
uploads/assets.zip 解压后的前端资源,工作副本为 assets_audit_src/。审计日期:2026-09-29。结论
资源包没有确认的远程代码执行或 SQL 注入原语。发现的主要风险集中在富文本编辑器的客户端协议过滤、以 GET 执行远程图片落盘、HTMX/Alpine 的动态执行能力,以及重复资源和第三方依赖缺少完整 provenance。
客户端净化不能替代服务端净化。当前 app/Helpers/Content.php 的服务端白名单、控制字符删除和 CSS 过滤提供了重要纵深防线,但编辑器预览仍可能先处理到未被客户端正确拦截的链接。
这是静态审计,不代表已在真实站点完成浏览器攻击、跨站请求、服务器配置或 PHP 运行时验证。
中危与条件性中危
中危A-01 客户端协议过滤可被控制字符绕过
js/editor.js:618-652;服务端对照:app/Helpers/Content.php:113-117编辑器将属性值转小写后,直接检查是否以 javascript: 开头,但没有先移除或规范化属性值中的空格、制表符、换行和控制字符。浏览器会把部分形式规范化为可执行的 javascript: 协议;已验证的例子包括 java\nscript:、java\tscript:。
href、src 和相关 URL 先删除 U+0000-U+0020、U+007F 等控制字符,再使用严格协议白名单;补充 CR/LF/Tab、HTML 实体和混合大小写测试。中危,条件性A-02 远程图片抓取使用 GET 且不带 CSRF
js/editor.js:2247-2275;app/Controllers/ApiController.php:191-249编辑器通过原生 XHR 调用 GET /api/fetch-image?url=...。后端要求登录并检查附件权限,也做了 host/IP 和逐跳重定向校验,但该写入上传目录的操作没有 CSRF token;编辑器调用也没有传 category_id。
中危,条件性A-03 HTMX/Alpine 允许动态表达式和脚本响应
lib/fhajax.js:16;lib/fhstate.js;app/Views/layouts/main.php:87-91本地 HTMX 兼容层默认启用 allowEval:true 和 allowScriptTags:true;Alpine 运行时包含基于 new Function 的表达式执行。若不可信响应、模板属性或可编辑数据进入这些处理路径,HTML 交换可能扩大为脚本执行。
hx-*/x-* 属性以及 CSP 是否存在。资源本身不能证明已形成可利用的 stored XSS,但动态执行面明显扩大。低危与维护风险
低危,条件性A-04 翻译文案被拼接到 innerHTML
js/editor.js:1002、js/auth.js:31;app/Views/layouts/main.php:72-78编辑器标签栏和密码强度提示使用 innerHTML 拼接 window.__t() 返回值。当前语言字典由服务端 JSON 安全注入,若字典只来自受信任代码文件,风险较低;若未来允许管理员或用户编辑翻译值,就会成为 DOM XSS 入口。
textContent 或 DOM 节点 API;确需图标 HTML 时分离固定模板和动态文字,禁止将翻译值直接作为 HTML 片段。低危,可靠性编辑器存在多个重复版本,容易产生安全修复漂移
js/editor.js、js/editor.php、js/editor_zip/editor.js、js/editor.zip资源包同时包含实际主文件、PHP 扩展名副本和嵌套压缩包副本。它们功能和行号存在差异;实际页面从 app/Views/layouts/main.php:66 加载 js/editor.js,但部署或打包流程若选择了其他副本,可能带入旧的净化逻辑。
低危,供应链第三方资源的版本与完整性元数据不完整
js/marked.min.js;js/turndown.js;js/turndown-plugin-gfm.js;lib/fhajax.js;lib/fhstate.js资源均为本地副本,未见 package lock、发布 hash、构建来源或统一的依赖清单。marked.min.js明确标注 v15.0.12,HTMX 兼容层标注 2.0.10,其他资源的版本和来源不完整。
已确认的正向控制
- 编辑器用独立
createHTMLDocument沙箱解析 HTML,并移除script、style、iframe、object、embed、svg等标签。 - 服务端
Content::sanitizeHtml()删除 raw-text 元素,限制标签/属性白名单,并在 URL 过滤前移除控制字符;sanitizeCssStyle()拦截url()、expression()、@import、javascript:等模式。 - 编辑器上传使用 POST 并附带 CSRF token;后端上传接口校验请求方法、Session、CSRF、版块附件权限和上传限流。
- 远程图片接口已实现 host/IP 内网阻断、DNS 解析后的 IP 校验和逐跳重定向检查;这些控制不抵消 GET/CSRF 设计问题。
- 本次对主要 JavaScript 资源和
editor.php做了 Node 语法解析检查,未发现语法错误;未发现直接的eval或命令执行调用,Alpine/HTMX 的框架级动态执行另列于 A-03。
资源范围
- 编辑器与交互:
js/editor.js、js/auth.js、js/lightbox.js、js/pow.js、js/thread.js。 - 本地依赖:
js/marked.min.js、js/turndown.js、js/turndown-plugin-gfm.js、lib/fhajax.js、lib/fhstate.js、lib/qrcode.min.js。 - 样式与主题:根目录 CSS、
css/themes/及嵌套themes.zip副本。 - PWA:
pwa/manifest.webmanifest与四个 PNG 图标资源。
检查结果与限制
- 浏览器验证了 URL 属性中的换行和制表符会被规范化为
javascript:协议形式;该结果用于支持 A-01。 - 没有 PHP CLI,未能运行
php -l或后端集成测试;editor.php已通过 JavaScript VM 解析检查。 - 没有完整入口、路由、生产 CSP、Cookie 属性、Web Server 配置和语言字典管理流程,因此 A-02 至 A-04 的公网影响需要部署验证。
- 未发现 CSS 外链、
expression()、-moz-binding或明显的恶意外连;本结论不替代依赖来源与 hash 验证。
建议修复顺序
- 先修复 A-01:统一客户端和服务端 URL 协议规范化,加入控制字符、实体和大小写组合测试。
- 将
/api/fetch-image改为 POST + CSRF,并显式携带真实category_id;继续执行响应大小上限和 SSRF 测试。 - 评估关闭 HTMX eval/script 响应和收紧 Alpine 指令,配合严格 CSP 做运行时防护。
- 将动态文案从
innerHTML改为textContent,删除或构建化管理编辑器重复副本。 - 补齐第三方依赖清单、版本、来源和 SHA-256,随后在真实站点做浏览器级 XSS、CSRF、上传和部署配置复测。
outputs/assets_audit_report.html。