From c5748437dbf6a6946a2939eae749e142d65f0d13 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Tue, 3 Dec 2024 18:18:50 +0000 Subject: [PATCH] LibWeb/CSP: Implement the default-src directive --- Libraries/LibWeb/CMakeLists.txt | 1 + .../Directives/DefaultSourceDirective.cpp | 73 +++++++++++++++++++ .../Directives/DefaultSourceDirective.h | 29 ++++++++ .../Directives/DirectiveFactory.cpp | 4 + Libraries/LibWeb/Forward.h | 1 + 5 files changed, 108 insertions(+) create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.cpp create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 4fe72fee0b6..b08e5a01e55 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -44,6 +44,7 @@ set(SOURCES Compression/DecompressionStream.cpp ContentSecurityPolicy/BlockingAlgorithms.cpp ContentSecurityPolicy/Directives/ConnectSourceDirective.cpp + ContentSecurityPolicy/Directives/DefaultSourceDirective.cpp ContentSecurityPolicy/Directives/Directive.cpp ContentSecurityPolicy/Directives/DirectiveFactory.cpp ContentSecurityPolicy/Directives/DirectiveOperations.cpp diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.cpp new file mode 100644 index 00000000000..c58bcbe6e1a --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::ContentSecurityPolicy::Directives { + +GC_DEFINE_ALLOCATOR(DefaultSourceDirective); + +DefaultSourceDirective::DefaultSourceDirective(String name, Vector value) + : Directive(move(name), move(value)) +{ +} + +// https://w3c.github.io/webappsec-csp/#default-src-pre-request +Directive::Result DefaultSourceDirective::pre_request_check(GC::Heap& 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, default-src and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::DefaultSrc, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. Return the result of executing the pre-request check for the directive whose name is name on request and + // policy, using this directive’s value for the comparison. + auto directive = create_directive(heap, name->to_string(), value()); + return directive->pre_request_check(heap, request, policy); +} + +// https://w3c.github.io/webappsec-csp/#default-src-post-request +Directive::Result DefaultSourceDirective::post_request_check(GC::Heap& 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, default-src and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::DefaultSrc, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. Return the result of executing the post-request check for the directive whose name is name on request, + // response, and policy, using this directive’s value for the comparison. + auto directive = create_directive(heap, name->to_string(), value()); + return directive->post_request_check(heap, request, response, policy); +} + +// https://w3c.github.io/webappsec-csp/#default-src-inline +Directive::Result DefaultSourceDirective::inline_check(GC::Heap& heap, GC::Ptr element, InlineType type, GC::Ref policy, String const& source) const +{ + // 1. 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); + + // 2. If the result of executing § 6.8.4 Should fetch directive execute on name, default-src and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::DefaultSrc, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. Otherwise, return the result of executing the inline check for the directive whose name is name on element, + // type, policy and source, using this directive’s value for the comparison. + auto directive = create_directive(heap, name.to_string(), value()); + return directive->inline_check(heap, element, type, policy, source); +} + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.h b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.h new file mode 100644 index 00000000000..66688835ce0 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DefaultSourceDirective.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-default-src +class DefaultSourceDirective final : public Directive { + GC_CELL(DefaultSourceDirective, Directive) + GC_DECLARE_ALLOCATOR(DefaultSourceDirective); + +public: + virtual ~DefaultSourceDirective() = 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: + DefaultSourceDirective(String name, Vector value); +}; + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp index 74ad8bd0ab8..f3302590c62 100644 --- a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,9 @@ GC::Ref create_directive(GC::Heap& heap, String name, Vector if (name == Names::ConnectSrc) return heap.allocate(move(name), move(value)); + if (name == Names::DefaultSrc) + return heap.allocate(move(name), move(value)); + if (name == Names::FontSrc) return heap.allocate(move(name), move(value)); diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 66f1997759a..8d64cf77744 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -133,6 +133,7 @@ struct SerializedPolicy; namespace Web::ContentSecurityPolicy::Directives { class ConnectSourceDirective; +class DefaultSourceDirective; class Directive; class FontSourceDirective; class FrameSourceDirective;