const ABOUT_BLANK: &str = "about:blank";
#[must_use]
pub fn is_allowed_navigation_url(url: &str, origin: &str) -> bool {
if url == ABOUT_BLANK || url == origin {
return true;
}
url.strip_prefix(origin)
.is_some_and(|rest| rest.starts_with('/'))
}
#[cfg(test)]
#[allow(clippy::disallowed_methods)]
mod tests {
use super::*;
const WEBUI: &str = "webui://app";
const HOSTED: &str = "https://app.webui.localhost";
#[test]
fn allows_the_app_origin_and_its_paths() {
assert!(is_allowed_navigation_url("webui://app", WEBUI));
assert!(is_allowed_navigation_url("webui://app/", WEBUI));
assert!(is_allowed_navigation_url("webui://app/settings", WEBUI));
assert!(is_allowed_navigation_url(HOSTED, HOSTED));
assert!(is_allowed_navigation_url(
"https://app.webui.localhost/index.html",
HOSTED
));
}
#[test]
fn allows_only_the_empty_document_from_the_about_scheme() {
assert!(is_allowed_navigation_url(ABOUT_BLANK, WEBUI));
assert!(!is_allowed_navigation_url("about:srcdoc", WEBUI));
assert!(!is_allowed_navigation_url("about:config", WEBUI));
assert!(!is_allowed_navigation_url("about:blank#x", WEBUI));
}
#[test]
fn rejects_origin_lookalikes() {
assert!(!is_allowed_navigation_url("webui://app.evil/", WEBUI));
assert!(!is_allowed_navigation_url("webui://application/", WEBUI));
assert!(!is_allowed_navigation_url("webui://appevil", WEBUI));
assert!(!is_allowed_navigation_url(
"https://app.webui.localhost.evil/",
HOSTED
));
}
#[test]
fn rejects_external_and_embedded_origins() {
assert!(!is_allowed_navigation_url("https://example.com/", WEBUI));
assert!(!is_allowed_navigation_url("https://webui://app/", WEBUI));
assert!(!is_allowed_navigation_url("javascript:alert(1)", WEBUI));
assert!(!is_allowed_navigation_url("file:///etc/passwd", WEBUI));
assert!(!is_allowed_navigation_url("", WEBUI));
}
}