diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dd70edb..da7b6a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - rust: ["1.70.0", "stable", "beta"] + rust: ["1.71.1", "stable", "beta"] os: [ubuntu-latest] cargo_params: ["--features=version-sync", "--features=serde"] steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 389043a..413c7fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Unreleased +# 0.5.3 + +* Minimum supported Rust version: 1.71.1 +* Fix default-src behavior with eval + # 0.5.2 * Minimum supported Rust version: 1.70 diff --git a/Cargo.toml b/Cargo.toml index 7a22521..0040040 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" documentation = "https://docs.rs/content-security-policy/" repository = "https://github.com/rust-ammonia/rust-content-security-policy" edition = "2018" -rust-version = "1.70" +rust-version = "1.71.1" exclude = [ "Cargo.nix", "default.nix", diff --git a/README.md b/README.md index 745bae4..b68d05b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Parse and validate Web [Content-Security-Policy level 3](https://www.w3.org/TR/CSP/) [![Crates.IO](https://img.shields.io/crates/v/content-security-policy.svg)](https://crates.rs/crates/content-security-policy) -![Requires rustc 1.70.0](https://img.shields.io/badge/rustc-1.70.0+-green.svg) +![Requires rustc 1.71.1](https://img.shields.io/badge/rustc-1.71.1+-green.svg) This function parses a CSP string into a data structure, and provides a bunch of functions you can call on it (basically all of the "hooks" defined in the CSP standard). It directly uses the `url` crate, but it's intentionally agnostic to your HTML parser and your networking stack, so there are a few things it doesn't do: diff --git a/src/lib.rs b/src/lib.rs index 56b0308..a26234b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -345,29 +345,39 @@ impl CspList { } /// https://www.w3.org/TR/CSP/#can-compile-strings pub fn is_js_evaluation_allowed(&self) -> CheckResult { - let mut allowed = CheckResult::Allowed; + let mut result = CheckResult::Allowed; for policy in &self.0 { - for directive in &policy.directive_set { - if matches!(allowed, CheckResult::Allowed) { - allowed = directive.is_js_evaluation_allowed(&policy); - if matches!(allowed, CheckResult::Blocked) { return CheckResult::Blocked }; - } + let source_list = policy.directive_set + .iter() + .find(|directive| directive.name == "script-src") + .or_else(|| policy.directive_set.iter().find(|directive| directive.name == "default-src")) + .map(|directive| SourceList(&directive.value)); + if let Some(source_list) = source_list { + result = match source_list.does_a_source_list_allow_js_evaluation(&policy.disposition) { + AllowResult::Allows => CheckResult::Allowed, + AllowResult::DoesNotAllow => CheckResult::Blocked, + }; } } - CheckResult::Allowed + result } /// https://www.w3.org/TR/CSP/#can-compile-wasm-bytes pub fn is_wasm_evaluation_allowed(&self) -> CheckResult { - let mut allowed = CheckResult::Allowed; + let mut result = CheckResult::Allowed; for policy in &self.0 { - for directive in &policy.directive_set { - if matches!(allowed, CheckResult::Allowed) { - allowed = directive.is_wasm_evaluation_allowed(&policy); - if matches!(allowed, CheckResult::Blocked) { return CheckResult::Blocked }; - } + let source_list = policy.directive_set + .iter() + .find(|directive| directive.name == "script-src") + .or_else(|| policy.directive_set.iter().find(|directive| directive.name == "default-src")) + .map(|directive| SourceList(&directive.value)); + if let Some(source_list) = source_list { + result = match source_list.does_a_source_list_allow_wasm_evaluation(&policy.disposition) { + AllowResult::Allows => CheckResult::Allowed, + AllowResult::DoesNotAllow => CheckResult::Blocked, + }; } } - CheckResult::Allowed + result } } @@ -1056,28 +1066,6 @@ impl Directive { _ => None, } } - /// https://www.w3.org/TR/CSP/#can-compile-strings - pub fn is_js_evaluation_allowed(&self, policy: &Policy) -> CheckResult { - let source_list = SourceList(&self.value); - match &self.name[..] { - "script-src" | "default-src" => match source_list.does_a_source_list_allow_js_evaluation(&policy.disposition) { - AllowResult::Allows => CheckResult::Allowed, - AllowResult::DoesNotAllow => CheckResult::Blocked, - }, - _ => CheckResult::Allowed - } - } - /// https://www.w3.org/TR/CSP/#can-compile-wasm-bytes - pub fn is_wasm_evaluation_allowed(&self, policy: &Policy) -> CheckResult { - let source_list = SourceList(&self.value); - match &self.name[..] { - "script-src" | "default-src" => match source_list.does_a_source_list_allow_wasm_evaluation(&policy.disposition) { - AllowResult::Allows => CheckResult::Allowed, - AllowResult::DoesNotAllow => CheckResult::Blocked - }, - _ => CheckResult::Allowed - } - } } /// https://www.w3.org/TR/CSP/#effective-directive-for-inline-check diff --git a/tests/examples.rs b/tests/examples.rs index 1bbe136..1cdea79 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -472,6 +472,21 @@ test_should_js_wasm_evaluation_be_blocked!{ kind: is_wasm_evaluation_allowed, result: Allowed ), + + // https://github.com/rust-ammonia/rust-content-security-policy/issues/48 + ( name: eval_webassembly_default_src_override, + policy: "default-src self; script-src self 'unsafe-eval'", + disposition: Enforce, + kind: is_wasm_evaluation_allowed, + result: Allowed + ), + ( name: eval_javascript_default_src_override, + policy: "default-src self; script-src self 'unsafe-eval'", + disposition: Enforce, + kind: is_js_evaluation_allowed, + result: Allowed + ), + ( name: eval_javascript_works_if_multiple_policies_were_passed, policy: "script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self';",