如果用户可以上传或分享文档,就有人能专门构造文件来攻击你的编辑器。Fabric.js JSON 安全之所以重要,是因为 Fabric.js 会把保存对象的每个键都复制到它创建的对象上。引擎会在 Fabric.js 看到文档之前检查每份文档。
默认检查的内容
- 原型污染。 名为
__proto__、constructor或prototype的键会先被删除,所以它们无法修改对象的原型。 - 不安全的图片地址。 每个图片地址都会在
assets.resolveUrl之后、发起任何请求之前检查。http:、https:、blob:、相对地址和data:image/...是允许的。javascript:、file:和非图片的data:地址会以UNSAFE_DOCUMENT拒绝。 - 大小。 超过 50,000 个对象或嵌套超过 100 层的文档,会在加载前被拒绝,恶意文件没法卡死标签页。
- SVG 导出。 文字会被转义,所以文本框里的
<script>仍然只是文字。
设置你自己的限制
createDocumentEngine({
canvas,
limits: {
maxObjects: 10_000,
maxDepth: 40,
isAllowedUrl: (url) => url.startsWith("https://cdn.example.com/"),
},
history: { limit: 100, maxBytes: 32 * 1024 * 1024 },
});maxObjects限制对象数量,maxDepth限制嵌套层数。isAllowedUrl替换默认的图片地址规则。只允许你提供图片的那些域名。history.maxBytes限制撤销历史占用的内存。
在服务器上检查上传
同样的检查在 Node 里无需画布也能运行。存储文件之前先检查:
import {
migrateDocument,
secureDocument,
validateDocument,
} from "fabricjs-document-engine";
export function acceptUpload(body: unknown) {
const safe = secureDocument(body, { maxObjects: 20000 });
const { document } = migrateDocument(safe, {
canvasWidth: 1200,
canvasHeight: 800,
});
const issues = validateDocument(document);
if (issues.length > 0) throw new Error("Invalid document");
return document;
}做好 Fabric.js JSON 安全,两边都要检查:浏览器里加载之前,服务器上存储之前。
报告安全问题
请通过 代码仓库 的 GitHub security advisories 私下报告安全问题,不要发在公开的 issue 里。