mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb/CSP: Implement the script-src directive
This commit is contained in:
parent
3d43462ccd
commit
0cff47828d
Notes:
github-actions[bot]
2025-07-09 21:53:59 +00:00
Author: https://github.com/Lubrsi
Commit: 0cff47828d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5328
Reviewed-by: https://github.com/ADKaster ✅
17 changed files with 839 additions and 14 deletions
|
@ -18,7 +18,7 @@ public:
|
|||
[[nodiscard]] GC::Ref<DOMStringMap> dataset();
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#dom-noncedelement-nonce
|
||||
String const& nonce() { return m_cryptographic_nonce; }
|
||||
String const& nonce() const { return m_cryptographic_nonce; }
|
||||
void set_nonce(String const& nonce) { m_cryptographic_nonce = nonce; }
|
||||
|
||||
void focus();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibTextCodec/Decoder.h>
|
||||
#include <LibWeb/Bindings/HTMLScriptElementPrototype.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
|
@ -274,8 +275,13 @@ void HTMLScriptElement::prepare_script()
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME: 19. If el does not have a src content attribute, and the Should element's inline behavior be blocked by Content Security Policy?
|
||||
// algorithm returns "Blocked" when given el, "script", and source text, then return. [CSP]
|
||||
// 19. If el does not have a src content attribute, and the Should element's inline behavior be blocked by Content Security Policy?
|
||||
// algorithm returns "Blocked" when given el, "script", and source text, then return. [CSP]
|
||||
if (!has_attribute(AttributeNames::src)
|
||||
&& ContentSecurityPolicy::should_elements_inline_type_behavior_be_blocked_by_content_security_policy(realm(), *this, ContentSecurityPolicy::Directives::Directive::InlineType::Script, source_text) == ContentSecurityPolicy::Directives::Directive::Result::Blocked) {
|
||||
dbgln("HTMLScriptElement: Refusing to run inline script because it violates the Content Security Policy.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 20. If el has an event attribute and a for attribute, and el's type is "classic", then:
|
||||
if (m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::event) && has_attribute(HTML::AttributeNames::for_)) {
|
||||
|
@ -325,7 +331,8 @@ void HTMLScriptElement::prepare_script()
|
|||
// 23. Let module script credentials mode be the CORS settings attribute credentials mode for el's crossorigin content attribute.
|
||||
auto module_script_credential_mode = cors_settings_attribute_credentials_mode(m_crossorigin);
|
||||
|
||||
// FIXME: 24. Let cryptographic nonce be el's [[CryptographicNonce]] internal slot's value.
|
||||
// 24. Let cryptographic nonce be el's [[CryptographicNonce]] internal slot's value.
|
||||
auto cryptographic_nonce = m_cryptographic_nonce;
|
||||
|
||||
// 25. If el has an integrity attribute, then let integrity metadata be that attribute's value.
|
||||
// Otherwise, let integrity metadata be the empty string.
|
||||
|
@ -350,7 +357,7 @@ void HTMLScriptElement::prepare_script()
|
|||
// credentials mode is module script credentials mode, referrer policy is referrer policy,
|
||||
// and fetch priority is fetch priority.
|
||||
ScriptFetchOptions options {
|
||||
.cryptographic_nonce = {}, // FIXME
|
||||
.cryptographic_nonce = move(cryptographic_nonce),
|
||||
.integrity_metadata = move(integrity_metadata),
|
||||
.parser_metadata = parser_metadata,
|
||||
.credentials_mode = module_script_credential_mode,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
|
||||
#include <LibWeb/Crypto/Crypto.h>
|
||||
#include <LibWeb/Fetch/FetchMethod.h>
|
||||
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
|
||||
|
@ -342,7 +343,9 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
|||
timeout = 0;
|
||||
|
||||
// FIXME: 5. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
|
||||
// FIXME: 6. Let realm be global's relevant realm.
|
||||
|
||||
// 6. Let realm be global's relevant realm.
|
||||
auto& realm = relevant_realm(this_impl());
|
||||
|
||||
// 7. Let initiating script be the active script.
|
||||
auto const* initiating_script = Web::Bindings::active_script();
|
||||
|
@ -352,7 +355,7 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
|||
// FIXME 8. Let uniqueHandle be null.
|
||||
|
||||
// 9. Let task be a task that runs the following substeps:
|
||||
auto task = GC::create_function(vm.heap(), Function<void()>([this, handler = move(handler), timeout, arguments = move(arguments), repeat, id, initiating_script, previous_id]() {
|
||||
auto task = GC::create_function(vm.heap(), Function<void()>([this, handler = move(handler), timeout, arguments = move(arguments), repeat, id, initiating_script, previous_id, &vm, &realm]() {
|
||||
// FIXME: 1. Assert: uniqueHandle is a unique internal value, not null.
|
||||
|
||||
// 2. If id does not exist in global's map of setTimeout and setInterval IDs, then abort these steps.
|
||||
|
@ -362,10 +365,11 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
|||
// FIXME: 3. If global's map of setTimeout and setInterval IDs[id] does not equal uniqueHandle, then abort these steps.
|
||||
// FIXME: 4. Record timing info for timer handler given handler, global's relevant settings object, and repeat.
|
||||
|
||||
handler.visit(
|
||||
bool continue_ = handler.visit(
|
||||
// 5. If handler is a Function, then invoke handler given arguments and "report", and with callback this value set to thisArg.
|
||||
[&](GC::Root<WebIDL::CallbackType> const& callback) {
|
||||
(void)WebIDL::invoke_callback(*callback, &this_impl(), WebIDL::ExceptionBehavior::Report, arguments);
|
||||
return true;
|
||||
},
|
||||
// 6. Otherwise:
|
||||
[&](String const& source) {
|
||||
|
@ -383,8 +387,14 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
|||
// FIXME: 4. Set handler to the result of invoking the Get Trusted Type compliant string algorithm with TrustedScript, global, handler, sink, and "script".
|
||||
}
|
||||
|
||||
// FIXME: 2. Assert: handler is a string.
|
||||
// FIXME: 3. Perform EnsureCSPDoesNotBlockStringCompilation(realm, « », handler, handler, timer, « », handler). If this throws an exception, catch it, report it for global, and abort these steps.
|
||||
// 2. Assert: handler is a string.
|
||||
// 3. Perform EnsureCSPDoesNotBlockStringCompilation(realm, « », handler, handler, timer, « », handler).
|
||||
// If this throws an exception, catch it, report it for global, and abort these steps.
|
||||
auto handler_primitive_string = JS::PrimitiveString::create(vm, source);
|
||||
if (auto result = ContentSecurityPolicy::ensure_csp_does_not_block_string_compilation(realm, {}, source, source, JS::CompilationType::Timer, {}, handler_primitive_string); result.is_throw_completion()) {
|
||||
report_exception(result, realm);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Let settings object be global's relevant settings object.
|
||||
auto& settings_object = relevant_settings_object(this_impl());
|
||||
|
@ -415,8 +425,12 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
|||
|
||||
// 9. Run the classic script script.
|
||||
(void)script->run();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!continue_)
|
||||
return;
|
||||
|
||||
// 7. If id does not exist in global's map of setTimeout and setInterval IDs, then abort these steps.
|
||||
if (!m_timers.contains(id))
|
||||
return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue