From a34f5d7ea1b317c5d104c95e10075cacf1881789 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 9 Mar 2022 15:47:23 -0700 Subject: [PATCH 1/2] Implement base URI --- Cargo.toml | 2 +- src/lib.rs | 27 +++++++++++++++++++++++++++ tests/base-uri.rs | 14 ++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/base-uri.rs diff --git a/Cargo.toml b/Cargo.toml index 8904d2e..703832c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ keywords = ["http", "csp", "security"] license = "MIT / Apache-2.0" readme = "README.md" documentation = "https://docs.rs/content-security-policy/" -repository = "https://github.com/notriddle/rust-content-security-policy" +repository = "https://github.com/rust-ammonia/rust-content-security-policy" edition = "2018" exclude = [ "Cargo.nix", diff --git a/src/lib.rs b/src/lib.rs index 454e69b..abf6212 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -281,6 +281,33 @@ impl CspList { } (result, violations) } + /** + https://www.w3.org/TR/CSP/#allow-base-for-document + + Note that, while this algoritm is defined as operating on a document, the only property it + actually uses is the document's CSP List. So this function operates on that. + */ + pub fn is_base_allowed_for_document(&self, base: &Url, self_origin: &Origin) -> (CheckResult, Vec) { + use CheckResult::*; + let mut violations = Vec::new(); + for policy in &self.0 { + let directive = policy.directive_set.iter().find(|directive| directive.name == "base-uri"); + if let Some(directive) = directive { + if SourceList(&directive.value).does_url_match_source_list_in_origin_with_redirect_count(base, &self_origin, 0) == DoesNotMatch { + let report_sample = directive.value.iter().any(|t| &t[..] == "'report-sample'"); + let violation = Violation { + directive: directive.clone(), + resource: ViolationResource::Inline { report_sample }, + }; + violations.push(violation); + if policy.disposition == PolicyDisposition::Enforce { + return (Blocked, violations); + } + } + } + } + return (Allowed, violations); + } } #[derive(Clone, Debug)] diff --git a/tests/base-uri.rs b/tests/base-uri.rs new file mode 100644 index 0000000..56658d9 --- /dev/null +++ b/tests/base-uri.rs @@ -0,0 +1,14 @@ +extern crate content_security_policy; +use content_security_policy::*; +#[test] +fn base_uri_test_allow() { + let csp_list = CspList::parse("base-uri https://www.notriddle.com", PolicySource::Header, PolicyDisposition::Enforce); + let (check_result, _) = csp_list.is_base_allowed_for_document(&Url::parse("https://www.notriddle.com").unwrap(), &Origin::new_opaque()); + assert_eq!(check_result, CheckResult::Allowed); +} +#[test] +fn base_uri_test_blocked() { + let csp_list = CspList::parse("base-uri https://www.example.com", PolicySource::Header, PolicyDisposition::Enforce); + let (check_result, _) = csp_list.is_base_allowed_for_document(&Url::parse("https://www.notriddle.com").unwrap(), &Origin::new_opaque()); + assert_eq!(check_result, CheckResult::Blocked); +} \ No newline at end of file From 8482de2d52471e3b6163d2fcb63483d1c07d88dc Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 9 Mar 2022 15:48:35 -0700 Subject: [PATCH 2/2] Disable default regex features, which CSP doesn't use --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 703832c..043405e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ exclude = [ [dependencies] url = "2" percent-encoding = "2.1" -regex = "1.1" +regex = { version = "1.1", default-features = false, features = ["std"] } bitflags = "1.3" version-sync = { version = "0.9", optional = true } serde = { version = "1.0", features = ["derive"], optional = true }