mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-21 16:58:58 +00:00
LibWeb: Implement Content Security Check for sink types
This commit is contained in:
parent
a5c631aff3
commit
ab82c4c5fc
Notes:
github-actions[bot]
2025-09-01 15:20:50 +00:00
Author: https://github.com/tete17
Commit: ab82c4c5fc
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5828
Reviewed-by: https://github.com/AtkinsSJ
Reviewed-by: https://github.com/Lubrsi ✅
2 changed files with 79 additions and 0 deletions
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <LibWeb/ContentSecurityPolicy/Directives/Names.h>
|
#include <LibWeb/ContentSecurityPolicy/Directives/Names.h>
|
||||||
#include <LibWeb/ContentSecurityPolicy/PolicyList.h>
|
#include <LibWeb/ContentSecurityPolicy/PolicyList.h>
|
||||||
|
#include <LibWeb/ContentSecurityPolicy/Violation.h>
|
||||||
#include <LibWeb/DOMURL/DOMURL.h>
|
#include <LibWeb/DOMURL/DOMURL.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/TrustedTypes/TrustedScript.h>
|
#include <LibWeb/TrustedTypes/TrustedScript.h>
|
||||||
|
@ -108,4 +109,79 @@ bool does_sink_require_trusted_types(JS::Object& global, String sink_group, Incl
|
||||||
// 2. Return false.
|
// 2. Return false.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/trusted-types/dist/spec/#should-block-sink-type-mismatch
|
||||||
|
ContentSecurityPolicy::Directives::Directive::Result should_sink_type_mismatch_violation_be_blocked_by_content_security_policy(JS::Object& global, TrustedTypes::InjectionSink sink, String sink_group, Utf16String source)
|
||||||
|
{
|
||||||
|
auto& realm = HTML::relevant_realm(global);
|
||||||
|
|
||||||
|
// 1. Let result be "Allowed".
|
||||||
|
auto result = ContentSecurityPolicy::Directives::Directive::Result::Allowed;
|
||||||
|
|
||||||
|
// 2. Let sample be source.
|
||||||
|
auto sample = source.substring_view(0);
|
||||||
|
|
||||||
|
// 3. If sink is "Function", then:
|
||||||
|
if (sink == TrustedTypes::InjectionSink::Function) {
|
||||||
|
// 1. If sample starts with "function anonymous", strip that from sample.
|
||||||
|
if (sample.starts_with("function anonymous"sv)) {
|
||||||
|
sample = sample.substring_view("function anonymous"sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Otherwise if sample starts with "async function anonymous", strip that from sample.
|
||||||
|
else if (sample.starts_with("async function anonymous"sv)) {
|
||||||
|
sample = sample.substring_view("async function anonymous"sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Otherwise if sample starts with "function* anonymous", strip that from sample.
|
||||||
|
else if (sample.starts_with("function* anonymous"sv)) {
|
||||||
|
sample = sample.substring_view("function* anonymous"sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Otherwise if sample starts with "async function* anonymous", strip that from sample.
|
||||||
|
else if (sample.starts_with("async function* anonymous"sv)) {
|
||||||
|
sample = sample.substring_view("async function* anonymous"sv.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. For each policy in global’s CSP list:
|
||||||
|
for (auto const policy : ContentSecurityPolicy::PolicyList::from_object(global)->policies()) {
|
||||||
|
// 1. If policy’s directive set does not contain a directive whose name is "require-trusted-types-for", skip to the next policy.
|
||||||
|
if (!policy->contains_directive_with_name(ContentSecurityPolicy::Directives::Names::RequireTrustedTypesFor))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 2. Let directive be the policy’s directive set’s directive whose name is "require-trusted-types-for"
|
||||||
|
auto const directive = policy->get_directive_by_name(ContentSecurityPolicy::Directives::Names::RequireTrustedTypesFor);
|
||||||
|
|
||||||
|
// 3. If directive’s value does not contain a trusted-types-sink-group which is a match for sinkGroup, skip to the next policy.
|
||||||
|
auto const maybe_sink_group = directive->value().find_if([&sink_group](auto const& directive_value) {
|
||||||
|
return directive_value.equals_ignoring_ascii_case(sink_group);
|
||||||
|
});
|
||||||
|
if (maybe_sink_group.is_end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 4. Let violation be the result of executing Create a violation object for global, policy, and directive on global, policy and "require-trusted-types-for"
|
||||||
|
auto violation = ContentSecurityPolicy::Violation::create_a_violation_object_for_global_policy_and_directive(realm, global, policy, ContentSecurityPolicy::Directives::Names::RequireTrustedTypesFor.to_string());
|
||||||
|
|
||||||
|
// 5. Set violation’s resource to "trusted-types-sink".
|
||||||
|
violation->set_resource(ContentSecurityPolicy::Violation::Resource::TrustedTypesSink);
|
||||||
|
|
||||||
|
// 6. Let trimmedSample be the substring of sample, containing its first 40 characters.
|
||||||
|
auto const trimmed_sample = sample.substring_view(0, min(sample.length_in_code_points(), 40));
|
||||||
|
|
||||||
|
// 7. Set violation’s sample to be the result of concatenating the list « sink, trimmedSample « using "|" as a separator.
|
||||||
|
violation->set_sample(MUST(String::formatted("{}|{}", to_string(sink), trimmed_sample)));
|
||||||
|
|
||||||
|
// 8. Execute Report a violation on violation.
|
||||||
|
violation->report_a_violation(realm);
|
||||||
|
|
||||||
|
// 9. If policy’s disposition is "enforce", then set result to "Blocked".
|
||||||
|
if (policy->disposition() == ContentSecurityPolicy::Policy::Disposition::Enforce)
|
||||||
|
result = ContentSecurityPolicy::Directives::Directive::Result::Blocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Return result.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <LibJS/Runtime/Object.h>
|
#include <LibJS/Runtime/Object.h>
|
||||||
#include <LibWeb/ContentSecurityPolicy/Directives/Directive.h>
|
#include <LibWeb/ContentSecurityPolicy/Directives/Directive.h>
|
||||||
|
#include <LibWeb/TrustedTypes/InjectionSink.h>
|
||||||
|
|
||||||
namespace Web::TrustedTypes {
|
namespace Web::TrustedTypes {
|
||||||
|
|
||||||
|
@ -32,4 +33,6 @@ private:
|
||||||
|
|
||||||
bool does_sink_require_trusted_types(JS::Object&, String, IncludeReportOnlyPolicies);
|
bool does_sink_require_trusted_types(JS::Object&, String, IncludeReportOnlyPolicies);
|
||||||
|
|
||||||
|
ContentSecurityPolicy::Directives::Directive::Result should_sink_type_mismatch_violation_be_blocked_by_content_security_policy(JS::Object& global, TrustedTypes::InjectionSink sink, String sink_group, Utf16String source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue