1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright 2026 Daniel Smith
// Licensed under the Apache License, Version 2.0
// See https://www.apache.org/licenses/LICENSE-2.0
//! Tier-aware sanitizers — Rust port of src/core/sanitizeByTier.ts.
//!
//! Consumers (renderers, anything that takes a validated link and
//! forwards it into a rendered surface) read provenance off each link
//! and apply the appropriate rule: strict on anything that crossed a
//! trust boundary (storage adapter, protocol handler, unstamped),
//! loose on author-tier links the developer hand-wrote.
//!
//! Fail-closed policy: a link with no provenance stamp is treated as
//! untrusted. `validate_config` stamps every link it returns, so the
//! only way an unstamped link ends up here is if it bypassed
//! validation — a code path that should not exist in normal use.
use cratelink_provenance;
use crate;
use crateLink;
/// Loose sanitize for author-tier, strict otherwise.
///
/// Author-tier gets [`sanitize_url`] (permits `tel:`, `mailto:`, and
/// any custom developer-intended scheme that is not explicitly
/// dangerous). Everything else — including unstamped — gets
/// [`sanitize_url_strict`] (http / https / mailto only).
/// Author keeps its `css_class`; everything else drops it (returns `None`).
///
/// Attacker-controlled class names can target CSS selectors that
/// exfiltrate data via `content: attr(...)`, trigger layout-driven
/// side channels, or overlay visible UI to mislead the user. There is
/// no narrow allowlist that beats "do not let untrusted input pick a
/// class at all."
/// Author passes `target_window` through (including `None`);
/// everything else clamps to `Some("_blank")` unconditionally.
///
/// Even when a non-author link did not specify its own target, we
/// still clamp to `_blank` rather than let it inherit the author's
/// named-window default (e.g. `"fromAlap"`). Letting a storage- or
/// protocol-tier link ride into an author-reserved window would let
/// it overwrite whatever the author had open there.