From f382bccc3dc406891425672b571fffb3b6d148b1 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Tue, 3 Dec 2024 15:24:07 +0000 Subject: [PATCH] LibWeb/CSP: Implement the script-src-elem directive --- Libraries/LibWeb/CMakeLists.txt | 1 + .../Directives/DirectiveFactory.cpp | 4 + .../ScriptSourceElementDirective.cpp | 76 +++++++++++++++++++ .../Directives/ScriptSourceElementDirective.h | 29 +++++++ Libraries/LibWeb/Forward.h | 1 + 5 files changed, 111 insertions(+) create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.cpp create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 33b5f61f2e6..63e5a614034 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -56,6 +56,7 @@ set(SOURCES ContentSecurityPolicy/Directives/Names.cpp ContentSecurityPolicy/Directives/ObjectSourceDirective.cpp ContentSecurityPolicy/Directives/ScriptSourceDirective.cpp + ContentSecurityPolicy/Directives/ScriptSourceElementDirective.cpp ContentSecurityPolicy/Directives/SerializedDirective.cpp ContentSecurityPolicy/Directives/SourceExpression.cpp ContentSecurityPolicy/Policy.cpp diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp index 14f8fa69cdd..98da5b3a510 100644 --- a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace Web::ContentSecurityPolicy::Directives { @@ -45,6 +46,9 @@ GC::Ref create_directive(GC::Heap& heap, String name, Vector if (name == Names::ScriptSrc) return heap.allocate(move(name), move(value)); + if (name == Names::ScriptSrcElem) + return heap.allocate(move(name), move(value)); + return heap.allocate(move(name), move(value)); } diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.cpp new file mode 100644 index 00000000000..72460bab2e8 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::ContentSecurityPolicy::Directives { + +GC_DEFINE_ALLOCATOR(ScriptSourceElementDirective); + +ScriptSourceElementDirective::ScriptSourceElementDirective(String name, Vector value) + : Directive(move(name), move(value)) +{ +} + +// https://w3c.github.io/webappsec-csp/#script-src-elem-pre-request +Directive::Result ScriptSourceElementDirective::pre_request_check(GC::Heap&, GC::Ref request, GC::Ref policy) const +{ + // 1. Let name be the result of executing § 6.8.1 Get the effective directive for request on request. + auto name = get_the_effective_directive_for_request(request); + + // 2. If the result of executing § 6.8.4 Should fetch directive execute on name, script-src-elem and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::ScriptSrcElem, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. Return the result of executing § 6.7.1.1 Script directives pre-request check on request, this directive, + // and policy. + return script_directives_pre_request_check(request, *this, policy); +} + +// https://w3c.github.io/webappsec-csp/#script-src-elem-post-request +Directive::Result ScriptSourceElementDirective::post_request_check(GC::Heap&, GC::Ref request, GC::Ref response, GC::Ref policy) const +{ + // 1. Let name be the result of executing § 6.8.1 Get the effective directive for request on request. + auto name = get_the_effective_directive_for_request(request); + + // 2. If the result of executing § 6.8.4 Should fetch directive execute on name, script-src-elem and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::ScriptSrcElem, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. Return the result of executing § 6.7.1.2 Script directives post-request check on request, response, this + // directive, and policy. + return script_directives_post_request_check(request, response, *this, policy); +} + +// https://w3c.github.io/webappsec-csp/#script-src-elem-inline +Directive::Result ScriptSourceElementDirective::inline_check(GC::Heap&, GC::Ptr element, InlineType type, GC::Ref policy, String const& source) const +{ + // 1. Assert: element is not null or type is "navigation". + VERIFY(element || type == InlineType::Navigation); + + // 2. Let name be the result of executing § 6.8.2 Get the effective directive for inline checks on type. + auto name = get_the_effective_directive_for_inline_checks(type); + + // 3. If the result of executing § 6.8.4 Should fetch directive execute on name, script-src-elem and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::ScriptSrcElem, policy) == ShouldExecute::No) + return Result::Allowed; + + // 4. If the result of executing § 6.7.3.3 Does element match source list for type and source? on element, this + // directive’s value, type, and source is "Does Not Match", return "Blocked". + if (does_element_match_source_list_for_type_and_source(element, value(), type, source) == MatchResult::DoesNotMatch) + return Result::Blocked; + + // 5. Return "Allowed". + return Result::Allowed; +} + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.h b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.h new file mode 100644 index 00000000000..209482c2561 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ScriptSourceElementDirective.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::ContentSecurityPolicy::Directives { + +// https://w3c.github.io/webappsec-csp/#directive-script-src-elem +class ScriptSourceElementDirective final : public Directive { + GC_CELL(ScriptSourceElementDirective, Directive) + GC_DECLARE_ALLOCATOR(ScriptSourceElementDirective); + +public: + virtual ~ScriptSourceElementDirective() = default; + + virtual Result pre_request_check(GC::Heap&, GC::Ref, GC::Ref) const override; + virtual Result post_request_check(GC::Heap&, GC::Ref, GC::Ref, GC::Ref) const override; + virtual Result inline_check(GC::Heap&, GC::Ptr, InlineType, GC::Ref, String const&) const override; + +private: + ScriptSourceElementDirective(String name, Vector value); +}; + +} diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 05f4ee9f72a..51013201c92 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -141,6 +141,7 @@ class ManifestSourceDirective; class MediaSourceDirective; class ObjectSourceDirective; class ScriptSourceDirective; +class ScriptSourceElementDirective; struct SerializedDirective; }