update
This commit is contained in:
@@ -35,8 +35,22 @@
|
||||
* 浏览器对 URL 会自动把 `\` 规范化成 `/`(Chrome/Firefox 都如此),
|
||||
* 校验放行 `\` 与 `/` 都不会引入新风险 —— 真实加载由 resolveRelativeImages 控。
|
||||
*/
|
||||
// 末尾 $ 锚整串;scheme / data:image / 纯锚点分支用 [^\s]* 兜底后续字符。
|
||||
// 顶层 `(?!)` 拒未在白名单的 scheme:相对路径分支 A (`[a-z+.-]+:[a-z\d.\-_]+(?![/\\])`)
|
||||
// 会让 `about:blank` / `javascript:foo` / `vbscript:foo` / `data:text/html` 同形态通过
|
||||
// —— 这里在外层把已知危险 / 未授权 scheme 统一拒掉,保留分支 A 的 Mac 文件名修复。
|
||||
// 相对路径分支:
|
||||
// A. `[a-z+.-]+:[a-z\d.\-_]+(?![/\\])` —— Mac/Linux 文件名带单冒号(如
|
||||
// `image:001.jpg`、`screenshot:1.png`),但 `:` 后不许是 `/` 或 `\`
|
||||
// (否则会误吃 `data:text/html`、`javascript:foo/bar` 之类)。
|
||||
// B. `[a-z+.-]+(?:[\\/][^/\\#]*)*` —— 多段路径,支持 `img/a.png` / `../up.md` /
|
||||
// `/abs/x.png` / Windows 反斜杠 / 路径段内含 `:`(如 `dir/sub:dir/file.png`)
|
||||
// / 段内 #fragment(如 `sprite.svg#icon-home`、`page.md#chapter`)。
|
||||
// `data:image/...` 在顶层 `(?!)` 里只拒 `data:text/html`(白名单分支仍允许
|
||||
// `data:image/png` 等栅格格式);非 IMG URI 由 isDangerousUriNonImg 兜底
|
||||
// javascript:/vbscript:/file:/data(?!:image\/),IMG 由 installHooks 的额外检查兜底。
|
||||
const ALLOWED_URI_REGEXP =
|
||||
/^(?:(?:https?|mailto|tel|callto|file):|data:image\/(?:png|jpe?g|gif|webp|bmp|ico|tiff);base64,|#|(?:(?![/\\]{2})[/\\]|[^a-z/\\])|[a-z+.-]+(?:[\\/][^a-z]*|$))/i;
|
||||
/^(?!about:|javascript:|vbscript:|data\s*:\s*text\s*\/\s*html)(?:(?:https?|mailto|tel|callto|file):[^\s]*|data:image\/(?:png|jpe?g|gif|webp|bmp|ico|tiff);base64,[^\s]*|#[^\s]*|(?:(?![/\\]{2})[/\\]|[^a-z/\\])[^\s]*|[a-z+.-]+:[a-z\d.\-_]+(?![/\\])|[a-z+.-]+(?:[\\/][^/\\#]*)*)$/i;
|
||||
|
||||
// data:image 单 URL 字节上限(防 OOM)。10 MB 对正常 AI 输出 + 用户内嵌图
|
||||
// 已经远超合理上限 —— Notes 单文件 5 MB 限制会先卡住写入,所以 10 MB 留余量。
|
||||
@@ -95,6 +109,9 @@ const DANGEROUS_STYLE_PATTERNS = [
|
||||
// url(javascript:...) / url("javascript:...") / url('javascript:...')
|
||||
// 容忍可选空白 + 单/双引号包裹 + 大小写
|
||||
/url\s*\(\s*['"]?\s*(?:javascript|vbscript|data\s*:\s*text\s*\/\s*html|file)\s*:/i,
|
||||
// 协议相对 URL(url(//evil.com/...)):浏览器按当前页协议补全为 http(s)://,
|
||||
// 绕过上面的 scheme 白名单,造成外部资源请求(IP / Referer / UA 泄露)。
|
||||
/url\s*\(\s*['"]?\s*\/\//i,
|
||||
// legacy IE CSS expression()
|
||||
/expression\s*\(/i,
|
||||
// legacy IE HTC behavior
|
||||
@@ -187,6 +204,18 @@ function installHooks(DOMPurifyInstance) {
|
||||
data.keepAttr = false;
|
||||
return;
|
||||
}
|
||||
// 显式拒未在白名单的 scheme:ALLOWED_URI_REGEXP 的分支 A
|
||||
// (`[a-z+.-]+:[a-z\d.\-_]+(?![/\\])`) 允许 Mac/Linux 文件名带单 `:`
|
||||
// (如 `image:001.jpg`),但形态上同 `javascript:foo` / `vbscript:foo` /
|
||||
// `about:blank` —— 后者也会通过 ALLOWED。isDangerousUriNonImg 只跑非 IMG
|
||||
// 路径且只覆盖危险 scheme,不含 `about:`,IMG 必须自己再拦一道。
|
||||
// data:text/html 在分支 A 里 `:text` 后续遇 `/` 被 `(?![/\\])` 否定、不通过;
|
||||
// 这里保留是为了防御性深度扫描(与 audit Sec-D 风格一致),同时挡住形如
|
||||
// `data:text/html;<script>` 等 `;` 后紧接 script payload 的边界情况。
|
||||
if (/^\s*(?:javascript|vbscript|data\s*:\s*text\s*\/\s*html|about\s*:)/i.test(data.attrValue)) {
|
||||
data.keepAttr = false;
|
||||
return;
|
||||
}
|
||||
// audit fix (Round 13 / Sec-H2):file:// 必须严格 file:///... 三斜杠形式
|
||||
// —— 拒绝 file://host/... 与 file:////host/...。
|
||||
//
|
||||
@@ -207,7 +236,7 @@ function installHooks(DOMPurifyInstance) {
|
||||
// 10 MB base64 ≈ 7.5 MB 二进制,对单张笔记内嵌图已远超合理范围。
|
||||
// 文件绝对路径/file:/https: 不进此分支,行为不变。
|
||||
data.attrValue.length > DATA_IMAGE_MAX_URL_LENGTH
|
||||
&& /^data:image\//i.test(data.attrValue)
|
||||
&& /^data:image\//i.test(data.attrValue.trim())
|
||||
) {
|
||||
data.keepAttr = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user