mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-04 00:27:47 +00:00
LibWeb: Finish algorithm to block trusted type policy creation with CSP
This is the mechanism that should pages to determine what kind of policies can be created on their domains mostly based around the HTTP headers the server responds with.
This commit is contained in:
parent
6398e771a3
commit
966e00fd69
Notes:
github-actions[bot]
2025-08-11 11:23:27 +00:00
Author: https://github.com/tete17
Commit: 966e00fd69
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5668
Reviewed-by: https://github.com/ADKaster
Reviewed-by: https://github.com/Lubrsi ✅
Reviewed-by: https://github.com/tcl3
8 changed files with 111 additions and 4 deletions
|
@ -56,6 +56,7 @@ set(SOURCES
|
|||
ContentSecurityPolicy/Directives/FrameSourceDirective.cpp
|
||||
ContentSecurityPolicy/Directives/ImageSourceDirective.cpp
|
||||
ContentSecurityPolicy/Directives/KeywordSources.cpp
|
||||
ContentSecurityPolicy/Directives/KeywordTrustedTypes.cpp
|
||||
ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp
|
||||
ContentSecurityPolicy/Directives/MediaSourceDirective.cpp
|
||||
ContentSecurityPolicy/Directives/Names.cpp
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Miguel Sacristán Izcue <miguel_tete17@hotmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/ContentSecurityPolicy/Directives/KeywordTrustedTypes.h>
|
||||
|
||||
namespace Web::ContentSecurityPolicy::Directives::KeywordTrustedTypes {
|
||||
|
||||
#define __ENUMERATE_KEYWORD_TRUSTED_TYPE(name, value) \
|
||||
FlyString name = value##_fly_string;
|
||||
ENUMERATE_KEYWORD_TRUSTED_TYPES
|
||||
#undef __ENUMERATE_KEYWORD_TRUSTED_TYPE
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Miguel Sacristán Izcue <miguel_tete17@hotmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
|
||||
namespace Web::ContentSecurityPolicy::Directives::KeywordTrustedTypes {
|
||||
|
||||
// https://www.w3.org/TR/trusted-types/#tt-keyword
|
||||
#define ENUMERATE_KEYWORD_TRUSTED_TYPES \
|
||||
__ENUMERATE_KEYWORD_TRUSTED_TYPE(AllowDuplicates, "'allow-duplicates'") \
|
||||
__ENUMERATE_KEYWORD_TRUSTED_TYPE(None, "'none'") \
|
||||
__ENUMERATE_KEYWORD_TRUSTED_TYPE(WildCard, "*")
|
||||
|
||||
#define __ENUMERATE_KEYWORD_TRUSTED_TYPE(name, value) extern FlyString name;
|
||||
ENUMERATE_KEYWORD_TRUSTED_TYPES
|
||||
#undef __ENUMERATE_KEYWORD_TRUSTED_TYPE
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ namespace Web::ContentSecurityPolicy::Directives::Names {
|
|||
__ENUMERATE_DIRECTIVE_NAME(StyleSrc, "style-src") \
|
||||
__ENUMERATE_DIRECTIVE_NAME(StyleSrcElem, "style-src-elem") \
|
||||
__ENUMERATE_DIRECTIVE_NAME(StyleSrcAttr, "style-src-attr") \
|
||||
__ENUMERATE_DIRECTIVE_NAME(TrustedTypes, "trusted-types") \
|
||||
__ENUMERATE_DIRECTIVE_NAME(WebRTC, "webrtc") \
|
||||
__ENUMERATE_DIRECTIVE_NAME(WorkerSrc, "worker-src")
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ class TrustedTypePolicy final : public Bindings::PlatformObject {
|
|||
public:
|
||||
virtual ~TrustedTypePolicy() override = default;
|
||||
|
||||
String const& name() const { return m_name; }
|
||||
|
||||
private:
|
||||
explicit TrustedTypePolicy(JS::Realm&, String const&, TrustedTypePolicyOptions const&);
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// https://w3c.github.io/trusted-types/dist/spec/#trusted-type-policy
|
||||
[Exposed=(Window,Worker)]
|
||||
interface TrustedTypePolicy {
|
||||
[FIXME] readonly attribute DOMString name;
|
||||
readonly attribute DOMString name;
|
||||
[FIXME] TrustedHTML createHTML(DOMString input, any... arguments);
|
||||
[FIXME] TrustedScript createScript(DOMString input, any... arguments);
|
||||
[FIXME] TrustedScriptURL createScriptURL(DOMString input, any... arguments);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/Directives/Directive.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/Directives/KeywordTrustedTypes.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/Directives/Names.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/PolicyList.h>
|
||||
#include <LibWeb/HTML/AttributeNames.h>
|
||||
|
@ -164,13 +165,12 @@ bool TrustedTypePolicyFactory::is_html(JS::Value value)
|
|||
}
|
||||
|
||||
// https://w3c.github.io/trusted-types/dist/spec/#create-trusted-type-policy-algorithm
|
||||
WebIDL::ExceptionOr<GC::Ref<TrustedTypePolicy>> TrustedTypePolicyFactory::create_a_trusted_type_policy(String const& policy_name, TrustedTypePolicyOptions const& options, JS::Object&)
|
||||
WebIDL::ExceptionOr<GC::Ref<TrustedTypePolicy>> TrustedTypePolicyFactory::create_a_trusted_type_policy(String const& policy_name, TrustedTypePolicyOptions const& options, JS::Object& global)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// TODO
|
||||
// 1. Let allowedByCSP be the result of executing Should Trusted Type policy creation be blocked by Content Security Policy? algorithm with global, policyName and factory’s created policy names value.
|
||||
auto const allowed_by_csp = ContentSecurityPolicy::Directives::Directive::Result::Blocked;
|
||||
auto const allowed_by_csp = should_trusted_type_policy_be_blocked_by_content_security_policy(global, policy_name, m_created_policy_names);
|
||||
|
||||
// 2. If allowedByCSP is "Blocked", throw a TypeError and abort further steps.
|
||||
if (allowed_by_csp == ContentSecurityPolicy::Directives::Directive::Result::Blocked)
|
||||
|
@ -196,6 +196,68 @@ WebIDL::ExceptionOr<GC::Ref<TrustedTypePolicy>> TrustedTypePolicyFactory::create
|
|||
return policy;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/trusted-types/#should-block-create-policy
|
||||
ContentSecurityPolicy::Directives::Directive::Result TrustedTypePolicyFactory::should_trusted_type_policy_be_blocked_by_content_security_policy(JS::Object& global, String const& policy_name, Vector<String> const& created_policy_names)
|
||||
{
|
||||
// 1. Let result be "Allowed".
|
||||
auto result = ContentSecurityPolicy::Directives::Directive::Result::Allowed;
|
||||
|
||||
// 2. For each policy in global’s CSP list:
|
||||
for (auto const policy : ContentSecurityPolicy::PolicyList::from_object(global)->policies()) {
|
||||
// 1. Let createViolation be false.
|
||||
bool create_violation = false;
|
||||
|
||||
// 2. If policy’s directive set does not contain a directive which name is "trusted-types", skip to the next policy.
|
||||
if (!policy->contains_directive_with_name(ContentSecurityPolicy::Directives::Names::TrustedTypes))
|
||||
continue;
|
||||
|
||||
// 3. Let directive be the policy’s directive set’s directive which name is "trusted-types"
|
||||
auto const directive = policy->get_directive_by_name(ContentSecurityPolicy::Directives::Names::TrustedTypes);
|
||||
|
||||
// 4. If directive’s value only contains a tt-keyword which is a match for a value 'none', set createViolation to true.
|
||||
if (directive->value().size() == 1 && directive->value().first().equals_ignoring_ascii_case(ContentSecurityPolicy::Directives::KeywordTrustedTypes::None))
|
||||
create_violation = true;
|
||||
|
||||
// 5. If createdPolicyNames contains policyName and directive’s value does not contain a tt-keyword which is a match for a value 'allow-duplicates', set createViolation to true.
|
||||
auto created_policy_names_iterator = created_policy_names.find(policy_name);
|
||||
if (!created_policy_names_iterator.is_end()) {
|
||||
auto maybe_allow_duplicates = directive->value().find_if([](auto const& directive_value) {
|
||||
return directive_value.equals_ignoring_ascii_case(ContentSecurityPolicy::Directives::KeywordTrustedTypes::AllowDuplicates);
|
||||
});
|
||||
if (maybe_allow_duplicates.is_end())
|
||||
create_violation = true;
|
||||
}
|
||||
|
||||
// 6. If directive’s value does not contain a tt-policy-name, which value is policyName, and directive’s value does not contain a tt-wildcard, set createViolation to true.
|
||||
auto directive_value_iterator = directive->value().find(policy_name);
|
||||
if (directive_value_iterator.is_end()) {
|
||||
auto maybe_wild_card = directive->value().find_if([](auto const& directive_value) {
|
||||
return directive_value.equals_ignoring_ascii_case(ContentSecurityPolicy::Directives::KeywordTrustedTypes::WildCard);
|
||||
});
|
||||
|
||||
if (maybe_wild_card.is_end())
|
||||
create_violation = true;
|
||||
}
|
||||
|
||||
// 7. If createViolation is false, skip to the next policy.
|
||||
if (!create_violation)
|
||||
continue;
|
||||
|
||||
// FIXME
|
||||
// 8. Let violation be the result of executing Create a violation object for global, policy, and directive on global, policy and "trusted-types"
|
||||
// 9. Set violation’s resource to "trusted-types-policy".
|
||||
// 10. Set violation’s sample to the substring of policyName, containing its first 40 characters.
|
||||
// 11. Execute Report a violation on violation.
|
||||
|
||||
// 12. If policy’s disposition is "enforce", then set result to "Blocked".
|
||||
if (policy->disposition() == ContentSecurityPolicy::Policy::Disposition::Enforce)
|
||||
result = ContentSecurityPolicy::Directives::Directive::Result::Blocked;
|
||||
}
|
||||
|
||||
// 3. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-get-trusted-type-data-for-attribute
|
||||
Optional<TrustedTypeData> get_trusted_type_data_for_attribute(String const& element, String const& attribute, Optional<String> const& attribute_ns)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <LibJS/Forward.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Bindings/TrustedTypePolicyFactoryPrototype.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/Directives/Directive.h>
|
||||
#include <LibWeb/TrustedTypes/TrustedTypePolicy.h>
|
||||
|
||||
namespace Web::TrustedTypes {
|
||||
|
@ -41,6 +42,7 @@ private:
|
|||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
WebIDL::ExceptionOr<GC::Ref<TrustedTypePolicy>> create_a_trusted_type_policy(String const&, TrustedTypePolicyOptions const&, JS::Object&);
|
||||
ContentSecurityPolicy::Directives::Directive::Result should_trusted_type_policy_be_blocked_by_content_security_policy(JS::Object&, String const&, Vector<String> const&);
|
||||
|
||||
// https://w3c.github.io/trusted-types/dist/spec/#trustedtypepolicyfactory-created-policy-names
|
||||
Vector<String> m_created_policy_names;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue