Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Libraries/LibWeb/Bindings/MainThreadVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@ void initialize_main_thread_vm(AgentType type)
};

// 8.1.6.3 HostGetCodeForEval(argument), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetcodeforeval(argument)
s_main_thread_vm->host_get_code_for_eval = [](JS::Object const&) -> GC::Ptr<JS::PrimitiveString> {
// FIXME: 1. If argument is a TrustedScript object, then return argument's data.
s_main_thread_vm->host_get_code_for_eval = [](JS::Object const& argument) -> GC::Ptr<JS::PrimitiveString> {
// 1. If argument is a TrustedScript object, then return argument's data.
if (auto const* trusted_script = as_if<TrustedTypes::TrustedScript>(argument); trusted_script)
return JS::PrimitiveString::create(argument.vm(), trusted_script->to_string());

// 2. Otherwise, return no-code.
return {};
Expand Down
87 changes: 78 additions & 9 deletions Libraries/LibWeb/ContentSecurityPolicy/BlockingAlgorithms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <LibWeb/HTML/WorkerGlobalScope.h>
#include <LibWeb/Infra/Strings.h>
#include <LibWeb/SRI/SRI.h>
#include <LibWeb/TrustedTypes/RequireTrustedTypesForDirective.h>
#include <LibWeb/TrustedTypes/TrustedTypePolicy.h>
#include <LibWeb/WebAssembly/WebAssembly.h>

namespace Web::ContentSecurityPolicy {
Expand Down Expand Up @@ -461,13 +463,81 @@ Directives::Directive::Result should_elements_inline_type_behavior_be_blocked_by
}

// https://w3c.github.io/webappsec-csp/#can-compile-strings
JS::ThrowCompletionOr<void> ensure_csp_does_not_block_string_compilation(JS::Realm& realm, ReadonlySpan<String>, StringView, StringView code_string, JS::CompilationType, ReadonlySpan<JS::Value>, JS::Value)
JS::ThrowCompletionOr<void> ensure_csp_does_not_block_string_compilation(JS::Realm& realm, ReadonlySpan<String> parameter_strings, StringView body_string, StringView code_string, JS::CompilationType compilation_type, ReadonlySpan<JS::Value> parameter_args, JS::Value body_arg)
{
// FIXME: 1. If compilationType is "TIMER", then:
// 1. Let sourceString be codeString.
StringView source_string = code_string;
// FIXME: 2. Else:
// FIXME: We don't do these two steps as we don't currently support Trusted Types.
Utf16String source_string;

// 1. If compilationType is "TIMER", then:
if (compilation_type == JS::CompilationType::Timer) {
// 1. Let sourceString be codeString.
source_string = Utf16String::from_utf8(code_string);
}
// 2. Else:
else {
// 1. Let compilationSink be "Function" if compilationType is "FUNCTION", and "eval" otherwise.
auto const compilation_sink = compilation_type == JS::CompilationType::Function ? TrustedTypes::InjectionSink::Function : TrustedTypes::InjectionSink::Eval;

// 2. Let isTrusted be true if bodyArg implements TrustedScript, and false otherwise.
auto is_trusted = body_arg.is_object() && is<TrustedTypes::TrustedScript>(body_arg.as_object());

// 3. If isTrusted is true then:
if (is_trusted) {
// 1. If bodyString is not equal to bodyArg’s data, set isTrusted to false.
if (body_string != as<TrustedTypes::TrustedScript>(body_arg.as_object()).to_string())
is_trusted = false;
}

// 4. If isTrusted is true, then:
if (is_trusted) {
// 1. Assert: parameterArgs’ [list/size=] is equal to [parameterStrings]' size.
VERIFY(parameter_args.size() == parameter_strings.size());

// 2. For each index of the range 0 to |parameterArgs]' [list/size=]:
for (size_t i = 0; i < parameter_args.size(); i++) {
// 1. Let arg be parameterArgs[index].
auto const& arg = parameter_args[i];

// 2. If arg implements TrustedScript, then:
if (arg.is_object() && is<TrustedTypes::TrustedScript>(arg.as_object())) {
// 1. if parameterStrings[index] is not equal to arg’s data, set isTrusted to false.
if (parameter_strings[i] != as<TrustedTypes::TrustedScript>(arg.as_object()).to_string()) {
is_trusted = false;
break;
}
}
// 3. Otherwise, set isTrusted to false.
else {
is_trusted = false;
break;
}
}
}

// 5. Let sourceToValidate be a new TrustedScript object created in realm whose data is set to codeString
// if isTrusted is true, and codeString otherwise.
auto const source_to_validate = is_trusted
? TrustedTypes::TrustedScriptOrString(realm.create<TrustedTypes::TrustedScript>(realm, Utf16String::from_utf8(code_string)))
: Utf16String::from_utf8(code_string);

// 6. Let sourceString be the result of executing the Get Trusted Type compliant string algorithm,
// with TrustedScript, realm, sourceToValidate, compilationSink, and 'script'.
auto maybe_source_string = TrustedTypes::get_trusted_type_compliant_string(
TrustedTypes::TrustedTypeName::TrustedScript,
realm.global_object(),
source_to_validate,
compilation_sink,
TrustedTypes::Script.to_string());

// 7. If the algorithm throws an error, throw an EvalError.
if (maybe_source_string.is_error()) {
return realm.vm().throw_completion<JS::EvalError>("Blocked by Content Security Policy"sv);
}
source_string = maybe_source_string.release_value();

// 8. If sourceString is not equal to codeString, throw an EvalError.
if (source_string != code_string)
return realm.vm().throw_completion<JS::EvalError>("Blocked by Content Security Policy"sv);
}

// 3. Let result be "Allowed".
auto result = Directives::Directive::Result::Allowed;
Expand Down Expand Up @@ -526,9 +596,8 @@ JS::ThrowCompletionOr<void> ensure_csp_does_not_block_string_compilation(JS::Rea
});

if (!maybe_report_sample.is_end()) {
Utf8View source_view { source_string };
auto sample = source_view.unicode_substring_view(0, min(source_view.length(), 40));
violation->set_sample(String::from_utf8_without_validation(sample.as_string().bytes()));
auto source_view = source_string.substring_view(0, min(source_string.length_in_code_units(), 40));
violation->set_sample(source_view.to_utf8_but_should_be_ported_to_utf16());
}

// 4. Execute § 5.5 Report a violation on violation.
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/TrustedTypes/InjectionSink.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace Web::TrustedTypes {
__ENUMERATE_INJECTION_SINKS(Element_insertAdjacentHTML, "Element insertAdjacentHTML") \
__ENUMERATE_INJECTION_SINKS(Element_outerHTML, "Element outerHTML") \
__ENUMERATE_INJECTION_SINKS(Element_setHTMLUnsafe, "Element setHTMLUnsafe") \
__ENUMERATE_INJECTION_SINKS(Eval, "eval") \
__ENUMERATE_INJECTION_SINKS(Function, "Function") \
__ENUMERATE_INJECTION_SINKS(HTMLIFrameElement_srcdoc, "HTMLIFrameElement srcdoc") \
__ENUMERATE_INJECTION_SINKS(HTMLScriptElement_innerText, "HTMLScriptElement innerText") \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Harness status: OK

Found 6 tests

6 Pass
Pass Blocked eval in Window.
Pass Blocked indirect eval in Window.
Pass Blocked Function constructor in Window.
Pass Blocked AsyncFunction constructor in Window.
Pass Blocked GeneratorFunction constructor in Window.
Pass Blocked AsyncGeneratorFunction constructor in Window.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Harness status: OK

Found 2 tests

2 Pass
Pass eval with plain string throws (both block).
Pass eval with TrustedScript throws (script-src blocks).
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Harness status: OK

Found 7 tests

7 Pass
Pass eval of TrustedScript works.
Pass indirect eval of TrustedScript works.
Pass eval of string works.
Pass indirect eval of string works.
Pass eval of !TrustedScript and !string works.
Pass Function constructor of TrustedScript works.
Pass Function constructor of string works.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Harness status: OK

Found 6 tests

6 Pass
Pass eval of string where default policy mutates value throws.
Pass indirect eval of string where default policy mutates value throws.
Pass Function constructor with string where default policy mutates value throws.
Pass AsyncFunction constructor with string where default policy mutates value throws.
Pass GeneratorFunction constructor with string where default policy mutates value throws.
Pass AsyncGeneratorFunction constructor with string where default policy mutates value throws.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Harness status: OK

Found 24 tests

24 Pass
Pass eval of TrustedScript works.
Pass indirect eval of TrustedScript works.
Pass eval of string works.
Pass eval of !TrustedScript and !string works.
Pass Function constructor of TrustedScript works.
Pass Function constructor of string works.
Pass Function constructor of all TrustedScripts works.
Pass Function constructor of all strings works.
Pass Function constructor of string and TrustedScript works.
Pass Async Function constructor of TrustedScript works.
Pass AsyncFunction constructor of string works.
Pass AsyncFunction constructor of all TrustedScripts works.
Pass AsyncFunction constructor of all strings works.
Pass AsyncFunction constructor of string and TrustedScript works.
Pass GeneratorFunction constructor of TrustedScript works.
Pass GeneratorFunction constructor of string works.
Pass GeneratorFunction constructor of all TrustedScripts works.
Pass GeneratorFunction constructor of all strings works.
Pass GeneratorFunction constructor of string and TrustedScript works.
Pass AsyncGeneratorFunction constructor of TrustedScript works.
Pass AsyncGeneratorFunction constructor of string works.
Pass AsyncGeneratorFunction constructor of all TrustedScripts works.
Pass AsyncGeneratorFunction constructor of all strings works.
Pass AsyncGeneratorFunction constructor of string and TrustedScript works.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Harness status: OK

Found 13 tests

13 Pass
Pass eval of TrustedScript works.
Pass indirect eval of TrustedScript works.
Pass eval of string fails.
Pass indirect eval of string fails.
Pass eval of !TrustedScript and !string works.
Pass Function constructor of TrustedScript works.
Pass Function constructor of string fails.
Pass Function constructor of all TrustedScripts works.
Pass Function constructor of all strings fails.
Pass Function constructor of string and TrustedScript fails.
Pass AsyncFunction constructor of string fails.
Pass GeneratorFunction constructor of string fails.
Pass AsyncGeneratorFunction constructor of string fails.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Harness status: OK

Found 16 tests

16 Pass
Pass plain string at index 0 (default policy modifying the function text).
Pass plain string at index 1 (default policy modifying the function text).
Pass plain string at index 2 (default policy modifying the function text).
Pass plain string at index 3 (default policy modifying the function text).
Pass plain string at index 0 (default policy leaving the function text unchanged).
Pass plain string at index 1 (default policy leaving the function text unchanged).
Pass plain string at index 2 (default policy leaving the function text unchanged).
Pass plain string at index 3 (default policy leaving the function text unchanged).
Pass TrustedScript with forged toString() at index 0 (default policy modifying the function text).
Pass TrustedScript with forged toString() at index 1 (default policy modifying the function text).
Pass TrustedScript with forged toString() at index 2 (default policy modifying the function text).
Pass TrustedScript with forged toString() at index 3 (default policy modifying the function text).
Pass TrustedScript with forged toString() at index 0 (default policy leaving the function text unchanged).
Pass TrustedScript with forged toString() at index 1 (default policy leaving the function text unchanged).
Pass TrustedScript with forged toString() at index 2 (default policy leaving the function text unchanged).
Pass TrustedScript with forged toString() at index 3 (default policy leaving the function text unchanged).
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Harness status: OK

Found 2 tests

2 Pass
Pass EvalError thrown if the callback of the default policy throws an error (eval).
Pass EvalError thrown if the callback of the default policy throws an error (new Function).
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Harness status: OK

Found 65 tests

65 Pass
Pass Function constructor with mixed plain and trusted strings, mask #0
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #0
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #0
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #0
Pass Function constructor with mixed plain and trusted strings, mask #1
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #1
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #1
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #1
Pass Function constructor with mixed plain and trusted strings, mask #2
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #2
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #2
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #2
Pass Function constructor with mixed plain and trusted strings, mask #3
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #3
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #3
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #3
Pass Function constructor with mixed plain and trusted strings, mask #4
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #4
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #4
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #4
Pass Function constructor with mixed plain and trusted strings, mask #5
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #5
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #5
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #5
Pass Function constructor with mixed plain and trusted strings, mask #6
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #6
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #6
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #6
Pass Function constructor with mixed plain and trusted strings, mask #7
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #7
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #7
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #7
Pass Function constructor with mixed plain and trusted strings, mask #8
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #8
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #8
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #8
Pass Function constructor with mixed plain and trusted strings, mask #9
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #9
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #9
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #9
Pass Function constructor with mixed plain and trusted strings, mask #10
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #10
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #10
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #10
Pass Function constructor with mixed plain and trusted strings, mask #11
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #11
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #11
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #11
Pass Function constructor with mixed plain and trusted strings, mask #12
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #12
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #12
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #12
Pass Function constructor with mixed plain and trusted strings, mask #13
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #13
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #13
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #13
Pass Function constructor with mixed plain and trusted strings, mask #14
Pass AsyncFunction constructor with mixed plain and trusted strings, mask #14
Pass GeneratorFunction constructor with mixed plain and trusted strings, mask #14
Pass AsyncGeneratorFunction constructor with mixed plain and trusted strings, mask #14
Pass Function constructor with mixed plain and trusted strings, mask #15
Pass Function constructor with trusted strings, and a forged toString() for the one at index 0
Pass Function constructor with trusted strings, and a forged toString() for the one at index 1
Pass Function constructor with trusted strings, and a forged toString() for the one at index 2
Pass Function constructor with trusted strings, and a forged toString() for the one at index 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Harness status: OK

Found 7 tests

7 Pass
Pass eval of TrustedScript works.
Pass indirect eval of TrustedScript works.
Pass eval of string works and does not call a default policy.
Pass indirect eval of string works and does not call a default policy.
Pass eval of !TrustedScript and !string works.
Pass Function constructor of TrustedScript works.
Pass Function constructor of string works and does not call a default policy.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Harness status: OK

Found 10 tests

10 Pass
Pass eval of TrustedScript works.
Pass indirect eval of TrustedScript works.
Pass eval of string works.
Pass indirect eval of string works.
Pass eval of !TrustedScript and !string works.
Pass Function constructor of TrustedScript works.
Pass Function constructor of all TrustedScripts works.
Pass Function constructor of string works.
Pass Function constructor of all strings works.
Pass Function constructor of string and TrustedScript works.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Harness status: OK

Found 1 tests

1 Pass
Pass Function constructor of stringified object and TrustedScript fails.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Harness status: OK

Found 9 tests

9 Pass
Pass eval with plain string with Trusted Types and permissive CSP throws (no type).
Pass indirect eval with plain string with Trusted Types and permissive CSP throws (no type).
Pass Function constructor with plain string with Trusted Types and permissive CSP throws (no type).
Pass eval with TrustedScript and permissive CSP works.
Pass indirect eval with TrustedScript and permissive CSP works.
Pass new Function with TrustedScript and permissive CSP works.
Pass eval with plain string with Trusted Types and permissive CSP works with default policy.
Pass indirect eval with plain string with Trusted Types and permissive CSP works with default policy.
Pass new Function with plain string default policy and permissive CSP works with default policy.
Loading
Loading