From 2bf0e0a6db5eac57f81fa6e6f94b7dff3aba9b4f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Dec 2024 10:15:21 -0700 Subject: [PATCH 1/2] Fix default-src override for script eval --- src/lib.rs | 60 +++++++++++++++++++---------------------------- tests/examples.rs | 15 ++++++++++++ 2 files changed, 39 insertions(+), 36 deletions(-) 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';", From b61db35dcc98ff8d6e759ebf45f257363a485a86 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Dec 2024 10:24:11 -0700 Subject: [PATCH 2/2] Bump changelog and MSRV to match dependencies --- .github/workflows/main.yml | 2 +- CHANGELOG.md | 5 +++++ Cargo.toml | 2 +- README.md | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) 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: