From 28f0117f069ee334c5c5a3a6fc1bb6a2988c4e4c Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 15 Jun 2026 11:19:46 +0800 Subject: [PATCH] =?UTF-8?q?test(sanitizer):=20=E8=A1=A5=E5=85=85=20is=5Fsa?= =?UTF-8?q?fe=5Furl=20=E5=88=86=E6=94=AF=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit is_safe_url 是 HTML 消毒器的安全核心,原仅通过 clean_html 间接覆盖。 新增 9 个直接单元测试,锁定各分支契约: - https/http 白名单通过 - javascript / vbscript scheme 拒绝(含大小写混淆) - data URI 按 allow_data_uri 标志决定(文章正文 vs 评论) - 相对路径与锚点片段通过 - 空字符串/纯空白视为安全 - mailto / tel / ftp 等其它白名单 scheme 通过 - 含空白的 scheme 名(混淆手法)被拒绝 共 17 个测试,全部通过。 --- src/api/sanitizer.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/api/sanitizer.rs b/src/api/sanitizer.rs index 9a5b30d..4b2b24a 100644 --- a/src/api/sanitizer.rs +++ b/src/api/sanitizer.rs @@ -435,4 +435,76 @@ mod tests { "x" ); } + + // ---- is_safe_url 直接分支测试 ---- + // is_safe_url 是安全敏感的内部函数,以下测试锁定其各分支的行为契约。 + + #[test] + fn is_safe_url_allows_https() { + let schemes = default_allowed_schemes(); + assert!(is_safe_url("https://example.com", &schemes, false)); + assert!(is_safe_url("http://example.com", &schemes, false)); + } + + #[test] + fn is_safe_url_rejects_javascript() { + let schemes = default_allowed_schemes(); + assert!(!is_safe_url("javascript:alert(1)", &schemes, false)); + } + + #[test] + fn is_safe_url_rejects_vbscript() { + let schemes = default_allowed_schemes(); + assert!(!is_safe_url("vbscript:msgbox", &schemes, false)); + } + + #[test] + fn is_safe_url_data_uri_respects_flag() { + let schemes = default_allowed_schemes(); + // 文章正文允许 data URI + assert!(is_safe_url("data:image/png;base64,iVBOR", &schemes, true)); + // 评论禁用 data URI + assert!(!is_safe_url("data:image/png;base64,iVBOR", &schemes, false)); + } + + #[test] + fn is_safe_url_allows_relative_and_fragment() { + let schemes = default_allowed_schemes(); + // 绝对路径 + assert!(is_safe_url("/path/to/page", &schemes, false)); + // 锚点 + assert!(is_safe_url("#section", &schemes, false)); + } + + #[test] + fn is_safe_url_empty_is_safe() { + let schemes = default_allowed_schemes(); + // 空 URL(如 img 无 src)视为安全。 + assert!(is_safe_url("", &schemes, false)); + assert!(is_safe_url(" ", &schemes, false)); + } + + #[test] + fn is_safe_url_allows_other_whitelisted_schemes() { + let schemes = default_allowed_schemes(); + // mailto / tel / ftp 等均在默认白名单中。 + assert!(is_safe_url("mailto:user@example.com", &schemes, false)); + assert!(is_safe_url("tel:+8613800138000", &schemes, false)); + assert!(is_safe_url("ftp://example.com/file", &schemes, false)); + } + + #[test] + fn is_safe_url_rejects_scheme_with_whitespace() { + let schemes = default_allowed_schemes(); + // 含空格的 scheme 名是已知的混淆手法,应被拒绝。 + assert!(!is_safe_url("java\tscript:alert(1)", &schemes, false)); + } + + #[test] + fn is_safe_url_scheme_matching_is_case_insensitive() { + let schemes = default_allowed_schemes(); + // scheme 大小写不敏感:HTTPS 与 https 等价。 + assert!(is_safe_url("HTTPS://example.com", &schemes, false)); + assert!(!is_safe_url("JAVASCRIPT:alert(1)", &schemes, false)); + } }