chat: parsed-URL link policy, cached link ranges, history byte budget (Phase 4)
CI / check (push) Failing after 3m10s
CI / check (push) Failing after 3m10s
Phase 4 of docs/chat-hardening-plan.md — URL and rendering resilience. Closes the chat-body half of S14 (bidi override strip). - sanitize: new is_safe_web_url shared link policy (url crate, promoted to a direct dependency): http/https scheme + non-empty host + no userinfo; candidates failing it stay plain text (their whole whitespace run, interior not re-scanned). Scheme detection is now ASCII-case-insensitive. - sanitize: linkify() -> link_ranges()/segments(): validated byte ranges computed once, exact-roundtrip slicing, at most CHAT_MSG_MAX_LINKS (8) clickable links per message; the rest stays selectable plain text. - sanitize_chat: strips bidi overrides/isolates (U+202A-202E, U+2066-2069) from message bodies while keeping ZWJ/ZWNJ/LRM/RLM (S14 chat-body half). - app: ChatEntry caches its link ranges (filled in push_chat), so redraws slice instead of rescanning/re-validating; only link spans allocate. - app: chat history now also bounded by 512 KiB total sanitized text (CHAT_HISTORY_MAX_TEXT_BYTES) alongside the 300-entry cap; the attachment byte cache is deliberately untouched by history eviction (own budgets). - app: AppMessage::OpenUrl re-checks the same parsed policy (defence in depth) instead of prefix checks - non-web schemes can never reach the opener even if the handler is invoked directly. 571 lib tests green (+3 net); clippy -D warnings + fmt clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Generated
+1
@@ -4894,6 +4894,7 @@ dependencies = [
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"url",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user