mirror of
https://github.com/lexmount/moli.git
synced 2026-10-07 00:01:00 +00:00
Apply the shared script nonceability check to parser scripts, buffered preloads and runtime script preparation. Suspicious script attribute names and values must not authorize execution merely because a nonce matches. Includes parser, preload and dynamic-preparation regressions. The attribute checks follow the [CSP3 nonceability algorithm](https://www.w3.org/TR/CSP3/#is-element-nonceable), including case-insensitive `<link`, `<script` and `<style` matches and parser duplicate attributes. Validation: all branch checks passed. Summary [ 115.690s] 18925 tests run: 18925 passed (9 slow), 16 skipped
70 lines
2.1 KiB
Rust
70 lines
2.1 KiB
Rust
/// Return whether a script element's nonce is safe to use for CSP matching.
|
|
///
|
|
/// CSP rejects nonces on parser elements with duplicate attributes or with an
|
|
/// attribute name/value containing `<script`, `<style`, or `<link`, preventing
|
|
/// dangling markup from borrowing a trusted nonce.
|
|
pub fn script_element_nonce_is_nonceable<'a>(
|
|
nonce: Option<&str>,
|
|
had_duplicate_attributes: bool,
|
|
attributes: impl IntoIterator<Item = (&'a str, &'a str)>,
|
|
) -> bool {
|
|
nonce.is_some()
|
|
&& !had_duplicate_attributes
|
|
&& attributes.into_iter().all(|(name, value)| {
|
|
!contains_nonce_breaking_markup(name) && !contains_nonce_breaking_markup(value)
|
|
})
|
|
}
|
|
|
|
fn contains_nonce_breaking_markup(value: &str) -> bool {
|
|
[
|
|
b"<script".as_slice(),
|
|
b"<style".as_slice(),
|
|
b"<link".as_slice(),
|
|
]
|
|
.into_iter()
|
|
.any(|needle| {
|
|
value
|
|
.as_bytes()
|
|
.windows(needle.len())
|
|
.any(|window| window.eq_ignore_ascii_case(needle))
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::script_element_nonce_is_nonceable;
|
|
|
|
#[test]
|
|
fn script_nonce_rejects_duplicate_or_markup_shaped_attributes() {
|
|
assert!(script_element_nonce_is_nonceable(
|
|
Some("abc"),
|
|
false,
|
|
[("nonce", "abc"), ("data-value", "safe")],
|
|
));
|
|
assert!(!script_element_nonce_is_nonceable(
|
|
None,
|
|
false,
|
|
[("data-value", "safe")],
|
|
));
|
|
assert!(!script_element_nonce_is_nonceable(
|
|
Some("abc"),
|
|
true,
|
|
[("nonce", "abc")],
|
|
));
|
|
|
|
for attributes in [
|
|
[("attribute<script", "safe"), ("nonce", "abc")],
|
|
[("attribute<style", "safe"), ("nonce", "abc")],
|
|
[("attribute", "value<ScRiPt"), ("nonce", "abc")],
|
|
[("attribute", "value<StYlE"), ("nonce", "abc")],
|
|
[("attribute", "value<LiNk"), ("nonce", "abc")],
|
|
] {
|
|
assert!(!script_element_nonce_is_nonceable(
|
|
Some("abc"),
|
|
false,
|
|
attributes,
|
|
));
|
|
}
|
|
}
|
|
}
|