aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--components/script/dom/document.rs14
-rw-r--r--components/script/dom/domimplementation.rs1
-rw-r--r--components/script/dom/domparser.rs2
-rw-r--r--components/script/dom/globalscope.rs48
-rw-r--r--components/script/dom/htmlheadelement.rs43
-rw-r--r--components/script/dom/htmlmetaelement.rs15
-rw-r--r--components/script/dom/macros.rs1
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/node.rs1
-rw-r--r--components/script/dom/request.rs7
-rw-r--r--components/script/dom/securitypolicyviolationevent.rs180
-rw-r--r--components/script/dom/servoparser/mod.rs1
-rw-r--r--components/script/dom/webidls/EventHandler.webidl1
-rw-r--r--components/script/dom/webidls/Request.webidl3
-rw-r--r--components/script/dom/webidls/SecurityPolicyViolationEvent.webidl41
-rw-r--r--components/script/dom/xmldocument.rs1
-rw-r--r--components/script/dom/xmlhttprequest.rs1
-rw-r--r--components/script/lib.rs2
-rw-r--r--components/script/script_runtime.rs73
-rw-r--r--components/script/script_thread.rs3
-rw-r--r--components/script/security_manager.rs177
-rw-r--r--components/script/timers.rs7
-rw-r--r--tests/wpt/include.ini5
-rw-r--r--tests/wpt/meta/content-security-policy/unsafe-eval/eval-blocked-in-about-blank-iframe.html.ini4
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini12
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-unsafe-eval-allows-wasm.any.js.ini9
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-wasm-unsafe-eval-allows-wasm.any.js.ini9
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini4
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini12
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini16
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-unsafe-eval-allows-wasm.any.js.ini9
-rw-r--r--tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-wasm-unsafe-eval-allows-wasm.any.js.ini9
-rw-r--r--tests/wpt/meta/html/dom/idlharness.https.html.ini24
-rw-r--r--tests/wpt/meta/html/semantics/document-metadata/the-meta-element/pragma-directives/http-equiv-enumerated-ascii-case-insensitive.html.ini3
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html.ini10
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js.ini1
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html.ini2
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html.ini2
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html.ini2
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html.ini2
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini1
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini1
-rw-r--r--tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html.ini31
-rw-r--r--tests/wpt/meta/html/webappapis/scripting/events/event-handler-all-global-events.html.ini3
-rw-r--r--tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini9
-rw-r--r--tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-frameset-window.html.ini9
-rw-r--r--tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html.ini6
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json4
-rw-r--r--tests/wpt/mozilla/tests/mozilla/interfaces.html1
-rw-r--r--tests/wpt/mozilla/tests/mozilla/interfaces.worker.js1
51 files changed, 755 insertions, 73 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7354d063263..cd001d0a1ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -976,9 +976,9 @@ dependencies = [
[[package]]
name = "content-security-policy"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "754c060c4a3342c5824d14caeba6c588716e9327f50558532685ef56718e0461"
+checksum = "bf7225464dae1993d0045c023d0975f44d63337f35f85faddb998ff9abdfcd0f"
dependencies = [
"base64",
"bitflags 2.6.0",
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 920834039d4..5dfe624a587 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -474,6 +474,8 @@ pub struct Document {
fonts: MutNullableDom<FontFaceSet>,
/// <https://html.spec.whatwg.org/multipage/#visibility-state>
visibility_state: Cell<DocumentVisibilityState>,
+ /// <https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>
+ status_code: Option<u16>,
}
#[derive(JSTraceable, MallocSizeOf)]
@@ -3001,6 +3003,10 @@ impl Document {
};
global_scope.report_an_error(error_info, HandleValue::null());
}
+
+ pub(crate) fn status_code(&self) -> Option<u16> {
+ self.status_code
+ }
}
fn is_character_value_key(key: &Key) -> bool {
@@ -3156,6 +3162,7 @@ impl Document {
doc_loader: DocumentLoader,
referrer: Option<String>,
referrer_policy: Option<ReferrerPolicy>,
+ status_code: Option<u16>,
canceller: FetchCanceller,
) -> Document {
let url = url.unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap());
@@ -3306,6 +3313,7 @@ impl Document {
resize_observers: Default::default(),
fonts: Default::default(),
visibility_state: Cell::new(DocumentVisibilityState::Hidden),
+ status_code,
}
}
@@ -3443,6 +3451,7 @@ impl Document {
docloader,
None,
None,
+ None,
Default::default(),
))
}
@@ -3461,6 +3470,7 @@ impl Document {
doc_loader: DocumentLoader,
referrer: Option<String>,
referrer_policy: Option<ReferrerPolicy>,
+ status_code: Option<u16>,
canceller: FetchCanceller,
) -> DomRoot<Document> {
Self::new_with_proto(
@@ -3477,6 +3487,7 @@ impl Document {
doc_loader,
referrer,
referrer_policy,
+ status_code,
canceller,
)
}
@@ -3496,6 +3507,7 @@ impl Document {
doc_loader: DocumentLoader,
referrer: Option<String>,
referrer_policy: Option<ReferrerPolicy>,
+ status_code: Option<u16>,
canceller: FetchCanceller,
) -> DomRoot<Document> {
let document = reflect_dom_object_with_proto(
@@ -3512,6 +3524,7 @@ impl Document {
doc_loader,
referrer,
referrer_policy,
+ status_code,
canceller,
)),
window,
@@ -3634,6 +3647,7 @@ impl Document {
DocumentLoader::new(&self.loader()),
None,
None,
+ None,
Default::default(),
);
new_doc
diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs
index 37712dd3d05..00224056009 100644
--- a/components/script/dom/domimplementation.rs
+++ b/components/script/dom/domimplementation.rs
@@ -155,6 +155,7 @@ impl DOMImplementationMethods for DOMImplementation {
loader,
None,
None,
+ None,
Default::default(),
);
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 6283514afe1..948736a0672 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -78,6 +78,7 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None,
+ None,
Default::default(),
);
ServoParser::parse_html_document(&document, Some(s), url);
@@ -98,6 +99,7 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None,
+ None,
Default::default(),
);
ServoParser::parse_xml_document(&document, Some(s), url);
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index acd9ac36a53..73ce73e75c1 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -18,7 +18,7 @@ use base::id::{
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
ServiceWorkerId, ServiceWorkerRegistrationId,
};
-use content_security_policy::CspList;
+use content_security_policy::{CheckResult, CspList, PolicyDisposition};
use crossbeam_channel::Sender;
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
use dom_struct::dom_struct;
@@ -28,14 +28,15 @@ use ipc_channel::router::ROUTER;
use js::glue::{IsWrapper, UnwrapObjectDynamic};
use js::jsapi::{
Compile1, CurrentGlobalOrNull, GetNonCCWObjectGlobal, HandleObject, Heap,
- InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, SetScriptPrivate,
+ InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, RuntimeCode,
+ SetScriptPrivate,
};
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
use js::panic::maybe_resume_unwind;
use js::rust::wrappers::{JS_ExecuteScript, JS_GetScriptPrivate};
use js::rust::{
- get_object_class, transform_str_to_source_text, CompileOptionsWrapper, HandleValue,
- MutableHandleValue, ParentRuntime, Runtime,
+ describe_scripted_caller, get_object_class, transform_str_to_source_text,
+ CompileOptionsWrapper, HandleValue, MutableHandleValue, ParentRuntime, Runtime,
};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use net_traits::blob_url_store::{get_blob_origin, BlobBuf};
@@ -119,6 +120,7 @@ use crate::script_runtime::{
CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan, ScriptPort,
};
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
+use crate::security_manager::CSPViolationReporter;
use crate::task::TaskCanceller;
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
use crate::task_source::file_reading::FileReadingTaskSource;
@@ -2773,6 +2775,37 @@ impl GlobalScope {
}))
}
+ #[allow(unsafe_code)]
+ pub fn is_js_evaluation_allowed(&self, cx: SafeJSContext) -> bool {
+ let Some(csp_list) = self.get_csp_list() else {
+ return true;
+ };
+
+ let scripted_caller = unsafe { describe_scripted_caller(*cx) }.unwrap_or_default();
+ let is_js_evaluation_allowed = csp_list.is_js_evaluation_allowed() == CheckResult::Allowed;
+
+ if !is_js_evaluation_allowed {
+ // FIXME: Don't fire event if `script-src` and `default-src`
+ // were not passed.
+ for policy in csp_list.0 {
+ let task = CSPViolationReporter::new(
+ self,
+ None,
+ policy.disposition == PolicyDisposition::Report,
+ RuntimeCode::JS,
+ scripted_caller.filename.clone(),
+ scripted_caller.line,
+ scripted_caller.col,
+ );
+ self.dom_manipulation_task_source()
+ .queue(task, self)
+ .unwrap();
+ }
+ }
+
+ is_js_evaluation_allowed
+ }
+
pub fn create_image_bitmap(
&self,
image: ImageBitmapSource,
@@ -3090,6 +3123,13 @@ impl GlobalScope {
None
}
+ pub fn status_code(&self) -> Option<u16> {
+ if let Some(window) = self.downcast::<Window>() {
+ return window.Document().status_code();
+ }
+ None
+ }
+
pub fn wgpu_id_hub(&self) -> Arc<Identities> {
self.gpu_id_hub.clone()
}
diff --git a/components/script/dom/htmlheadelement.rs b/components/script/dom/htmlheadelement.rs
index 9fd83041016..2fd4b8f3b5b 100644
--- a/components/script/dom/htmlheadelement.rs
+++ b/components/script/dom/htmlheadelement.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use content_security_policy::{CspList, PolicyDisposition, PolicySource};
use dom_struct::dom_struct;
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
use js::rust::HandleObject;
@@ -80,6 +81,48 @@ impl HTMLHeadElement {
}
}
}
+
+ /// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
+ pub fn set_content_security_policy(&self) {
+ let doc = document_from_node(self);
+
+ if doc.GetHead().as_deref() != Some(self) {
+ return;
+ }
+
+ let mut csp_list: Option<CspList> = None;
+ let node = self.upcast::<Node>();
+ let candinates = node
+ .traverse_preorder(ShadowIncluding::No)
+ .filter_map(DomRoot::downcast::<Element>)
+ .filter(|elem| elem.is::<HTMLMetaElement>())
+ .filter(|elem| {
+ elem.get_string_attribute(&local_name!("http-equiv"))
+ .to_ascii_lowercase() ==
+ "content-security-policy".to_owned()
+ })
+ .filter(|elem| {
+ elem.get_attribute(&ns!(), &local_name!("content"))
+ .is_some()
+ });
+
+ for meta in candinates {
+ if let Some(ref content) = meta.get_attribute(&ns!(), &local_name!("content")) {
+ let content = content.value();
+ let content_val = content.trim();
+ if !content_val.is_empty() {
+ let policies =
+ CspList::parse(content_val, PolicySource::Meta, PolicyDisposition::Enforce);
+ match csp_list {
+ Some(ref mut csp_list) => csp_list.append(policies),
+ None => csp_list = Some(policies),
+ }
+ }
+ }
+ }
+
+ doc.set_csp_list(csp_list);
+ }
}
impl VirtualMethods for HTMLHeadElement {
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index 60efbb474cb..1cbd709ae1a 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -88,8 +88,10 @@ impl HTMLMetaElement {
// https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv
} else if !self.HttpEquiv().is_empty() {
// TODO: Implement additional http-equiv candidates
- if self.HttpEquiv().to_ascii_lowercase().as_str() == "refresh" {
- self.declarative_refresh();
+ match self.HttpEquiv().to_ascii_lowercase().as_str() {
+ "refresh" => self.declarative_refresh(),
+ "content-security-policy" => self.apply_csp_list(),
+ _ => {},
}
}
}
@@ -115,6 +117,15 @@ impl HTMLMetaElement {
}
}
+ /// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
+ fn apply_csp_list(&self) {
+ if let Some(parent) = self.upcast::<Node>().GetParentElement() {
+ if let Some(head) = parent.downcast::<HTMLHeadElement>() {
+ head.set_content_security_policy();
+ }
+ }
+ }
+
/// <https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps>
fn declarative_refresh(&self) {
// 2
diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs
index fb57bd502a4..30bb6bcfe4f 100644
--- a/components/script/dom/macros.rs
+++ b/components/script/dom/macros.rs
@@ -471,6 +471,7 @@ macro_rules! global_event_handlers(
event_handler!(progress, GetOnprogress, SetOnprogress);
event_handler!(ratechange, GetOnratechange, SetOnratechange);
event_handler!(reset, GetOnreset, SetOnreset);
+ event_handler!(securitypolicyviolation, GetOnsecuritypolicyviolation, SetOnsecuritypolicyviolation);
event_handler!(seeked, GetOnseeked, SetOnseeked);
event_handler!(seeking, GetOnseeking, SetOnseeking);
event_handler!(select, GetOnselect, SetOnselect);
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 616dd576a5c..8c1d40ea8af 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -525,6 +525,7 @@ pub(crate) mod rtcrtptransceiver;
pub mod rtcsessiondescription;
pub mod rtctrackevent;
pub mod screen;
+pub mod securitypolicyviolationevent;
pub mod selection;
pub mod serviceworker;
pub mod serviceworkercontainer;
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 418bc2e6b04..316f63ce191 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -2296,6 +2296,7 @@ impl Node {
loader,
None,
None,
+ document.status_code(),
Default::default(),
);
DomRoot::upcast::<Node>(document)
diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs
index 999211e8a2b..48499901c5d 100644
--- a/components/script/dom/request.rs
+++ b/components/script/dom/request.rs
@@ -720,8 +720,11 @@ impl From<RequestDestination> for NetTraitsRequestDestination {
RequestDestination::Document => NetTraitsRequestDestination::Document,
RequestDestination::Embed => NetTraitsRequestDestination::Embed,
RequestDestination::Font => NetTraitsRequestDestination::Font,
+ RequestDestination::Frame => NetTraitsRequestDestination::Frame,
+ RequestDestination::Iframe => NetTraitsRequestDestination::IFrame,
RequestDestination::Image => NetTraitsRequestDestination::Image,
RequestDestination::Manifest => NetTraitsRequestDestination::Manifest,
+ RequestDestination::Json => NetTraitsRequestDestination::Json,
RequestDestination::Object => NetTraitsRequestDestination::Object,
RequestDestination::Report => NetTraitsRequestDestination::Report,
RequestDestination::Script => NetTraitsRequestDestination::Script,
@@ -743,8 +746,11 @@ impl From<NetTraitsRequestDestination> for RequestDestination {
NetTraitsRequestDestination::Document => RequestDestination::Document,
NetTraitsRequestDestination::Embed => RequestDestination::Embed,
NetTraitsRequestDestination::Font => RequestDestination::Font,
+ NetTraitsRequestDestination::Frame => RequestDestination::Frame,
+ NetTraitsRequestDestination::IFrame => RequestDestination::Iframe,
NetTraitsRequestDestination::Image => RequestDestination::Image,
NetTraitsRequestDestination::Manifest => RequestDestination::Manifest,
+ NetTraitsRequestDestination::Json => RequestDestination::Json,
NetTraitsRequestDestination::Object => RequestDestination::Object,
NetTraitsRequestDestination::Report => RequestDestination::Report,
NetTraitsRequestDestination::Script => RequestDestination::Script,
@@ -759,6 +765,7 @@ impl From<NetTraitsRequestDestination> for RequestDestination {
NetTraitsRequestDestination::Video => RequestDestination::Video,
NetTraitsRequestDestination::Worker => RequestDestination::Worker,
NetTraitsRequestDestination::Xslt => RequestDestination::Xslt,
+ NetTraitsRequestDestination::WebIdentity => RequestDestination::_empty,
}
}
}
diff --git a/components/script/dom/securitypolicyviolationevent.rs b/components/script/dom/securitypolicyviolationevent.rs
new file mode 100644
index 00000000000..edbaf7d04dc
--- /dev/null
+++ b/components/script/dom/securitypolicyviolationevent.rs
@@ -0,0 +1,180 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use dom_struct::dom_struct;
+use js::rust::HandleObject;
+use servo_atoms::Atom;
+
+use super::bindings::reflector::reflect_dom_object_with_proto;
+use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
+use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding::{
+ SecurityPolicyViolationEventDisposition, SecurityPolicyViolationEventInit,
+ SecurityPolicyViolationEventMethods,
+};
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::{DOMString, USVString};
+use crate::dom::event::{Event, EventBubbles, EventCancelable};
+use crate::dom::globalscope::GlobalScope;
+
+// https://w3c.github.io/webappsec-csp/#securitypolicyviolationevent
+#[dom_struct]
+pub struct SecurityPolicyViolationEvent {
+ event: Event,
+ document_uri: USVString,
+ referrer: USVString,
+ blocked_uri: USVString,
+ effective_directive: DOMString,
+ violated_directive: DOMString,
+ original_policy: DOMString,
+ source_file: USVString,
+ sample: DOMString,
+ disposition: SecurityPolicyViolationEventDisposition,
+ status_code: u16,
+ line_number: u32,
+ column_number: u32,
+}
+
+impl SecurityPolicyViolationEvent {
+ fn new_inherited(init: &SecurityPolicyViolationEventInit) -> SecurityPolicyViolationEvent {
+ SecurityPolicyViolationEvent {
+ event: Event::new_inherited(),
+ document_uri: init.documentURI.clone(),
+ referrer: init.referrer.clone(),
+ blocked_uri: init.blockedURI.clone(),
+ effective_directive: init.effectiveDirective.clone(),
+ violated_directive: init.violatedDirective.clone(),
+ original_policy: init.originalPolicy.clone(),
+ source_file: init.sourceFile.clone(),
+ sample: init.sample.clone(),
+ disposition: init.disposition.clone(),
+ status_code: init.statusCode,
+ line_number: init.lineNumber,
+ column_number: init.columnNumber,
+ }
+ }
+
+ pub fn new_initialized(
+ global: &GlobalScope,
+ init: &SecurityPolicyViolationEventInit,
+ proto: Option<HandleObject>,
+ ) -> DomRoot<SecurityPolicyViolationEvent> {
+ reflect_dom_object_with_proto(
+ Box::new(SecurityPolicyViolationEvent::new_inherited(init)),
+ global,
+ proto,
+ )
+ }
+
+ fn new_with_proto(
+ global: &GlobalScope,
+ proto: Option<HandleObject>,
+ type_: Atom,
+ bubbles: EventBubbles,
+ cancelable: EventCancelable,
+ init: &SecurityPolicyViolationEventInit,
+ ) -> DomRoot<Self> {
+ let ev = SecurityPolicyViolationEvent::new_initialized(global, init, proto);
+ {
+ let event = ev.upcast::<Event>();
+ event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
+ }
+ ev
+ }
+
+ pub fn new(
+ global: &GlobalScope,
+ type_: Atom,
+ bubbles: EventBubbles,
+ cancelable: EventCancelable,
+ init: &SecurityPolicyViolationEventInit,
+ ) -> DomRoot<Self> {
+ Self::new_with_proto(global, None, type_, bubbles, cancelable, init)
+ }
+
+ #[allow(non_snake_case)]
+ pub fn Constructor(
+ global: &GlobalScope,
+ proto: Option<HandleObject>,
+ type_: DOMString,
+ init: &SecurityPolicyViolationEventInit,
+ ) -> DomRoot<Self> {
+ SecurityPolicyViolationEvent::new_with_proto(
+ global,
+ proto,
+ Atom::from(type_),
+ EventBubbles::from(init.parent.bubbles),
+ EventCancelable::from(init.parent.cancelable),
+ init,
+ )
+ }
+}
+
+#[allow(non_snake_case)]
+impl SecurityPolicyViolationEventMethods for SecurityPolicyViolationEvent {
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-documenturi>
+ fn DocumentURI(&self) -> USVString {
+ self.document_uri.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-referrer>
+ fn Referrer(&self) -> USVString {
+ self.referrer.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-blockeduri>
+ fn BlockedURI(&self) -> USVString {
+ self.blocked_uri.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-effectivedirective>
+ fn EffectiveDirective(&self) -> DOMString {
+ self.effective_directive.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-violateddirective>
+ fn ViolatedDirective(&self) -> DOMString {
+ self.violated_directive.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-originalpolicy>
+ fn OriginalPolicy(&self) -> DOMString {
+ self.original_policy.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-sourcefile>
+ fn SourceFile(&self) -> USVString {
+ self.source_file.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-sample>
+ fn Sample(&self) -> DOMString {
+ self.sample.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-disposition>
+ fn Disposition(&self) -> SecurityPolicyViolationEventDisposition {
+ self.disposition.clone()
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-statuscode>
+ fn StatusCode(&self) -> u16 {
+ self.status_code
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-linenumber>
+ fn LineNumber(&self) -> u32 {
+ self.line_number
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-columnnumber>
+ fn ColumnNumber(&self) -> u32 {
+ self.column_number
+ }
+
+ /// <https://dom.spec.whatwg.org/#dom-event-istrusted>
+ fn IsTrusted(&self) -> bool {
+ self.event.IsTrusted()
+ }
+}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index 138aa8d4546..33e2948d375 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -214,6 +214,7 @@ impl ServoParser {
loader,
None,
None,
+ None,
Default::default(),
);
diff --git a/components/script/dom/webidls/EventHandler.webidl b/components/script/dom/webidls/EventHandler.webidl
index 4303bb19532..f597ce237d3 100644
--- a/components/script/dom/webidls/EventHandler.webidl
+++ b/components/script/dom/webidls/EventHandler.webidl
@@ -77,6 +77,7 @@ interface mixin GlobalEventHandlers {
attribute EventHandler onreset;
attribute EventHandler onresize;
attribute EventHandler onscroll;
+ attribute EventHandler onsecuritypolicyviolation;
attribute EventHandler onseeked;
attribute EventHandler onseeking;
attribute EventHandler onselect;
diff --git a/components/script/dom/webidls/Request.webidl b/components/script/dom/webidls/Request.webidl
index 048636c1e8b..78a45de208e 100644
--- a/components/script/dom/webidls/Request.webidl
+++ b/components/script/dom/webidls/Request.webidl
@@ -47,7 +47,10 @@ enum RequestDestination {
"document",
"embed",
"font",
+ "frame",
+ "iframe",
"image",
+ "json",
"manifest",
"object",
"report",
diff --git a/components/script/dom/webidls/SecurityPolicyViolationEvent.webidl b/components/script/dom/webidls/SecurityPolicyViolationEvent.webidl
new file mode 100644
index 00000000000..6b34c30f719
--- /dev/null
+++ b/components/script/dom/webidls/SecurityPolicyViolationEvent.webidl
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+// https://w3c.github.io/webappsec-csp/#securitypolicyviolationevent
+
+enum SecurityPolicyViolationEventDisposition {
+ "enforce", "report"
+};
+
+[Exposed=(Window,Worker)]
+interface SecurityPolicyViolationEvent : Event {
+ constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict = {});
+ readonly attribute USVString documentURI;
+ readonly attribute USVString referrer;
+ readonly attribute USVString blockedURI;
+ readonly attribute DOMString effectiveDirective;
+ readonly attribute DOMString violatedDirective; // historical alias of effectiveDirective
+ readonly attribute DOMString originalPolicy;
+ readonly attribute USVString sourceFile;
+ readonly attribute DOMString sample;
+ readonly attribute SecurityPolicyViolationEventDisposition disposition;
+ readonly attribute unsigned short statusCode;
+ readonly attribute unsigned long lineNumber;
+ readonly attribute unsigned long columnNumber;
+};
+
+dictionary SecurityPolicyViolationEventInit : EventInit {
+ USVString documentURI = "";
+ USVString referrer = "";
+ USVString blockedURI = "";
+ DOMString violatedDirective = "";
+ DOMString effectiveDirective = "";
+ DOMString originalPolicy = "";
+ USVString sourceFile = "";
+ DOMString sample = "";
+ SecurityPolicyViolationEventDisposition disposition = "enforce";
+ unsigned short statusCode = 0;
+ unsigned long lineNumber = 0;
+ unsigned long columnNumber = 0;
+};
diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs
index 627e0427a6a..f7da09c8d51 100644
--- a/components/script/dom/xmldocument.rs
+++ b/components/script/dom/xmldocument.rs
@@ -55,6 +55,7 @@ impl XMLDocument {
doc_loader,
None,
None,
+ None,
Default::default(),
),
}
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 33fcc0a493f..d57f2f73d2c 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -1527,6 +1527,7 @@ impl XMLHttpRequest {
docloader,
None,
None,
+ None,
Default::default(),
)
}
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 57d8427cd8c..b145e83227a 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -68,6 +68,8 @@ pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
#[warn(deprecated)]
+pub mod security_manager;
+#[warn(deprecated)]
pub mod serviceworker_manager;
#[warn(deprecated)]
mod stylesheet_loader;
diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs
index b40795a15fb..9c9efe54017 100644
--- a/components/script/script_runtime.rs
+++ b/components/script/script_runtime.rs
@@ -19,6 +19,8 @@ use std::time::{Duration, Instant};
use std::{fmt, os, ptr, thread};
use base::id::PipelineId;
+use content_security_policy::{CheckResult, PolicyDisposition};
+use js::conversions::jsstr_to_string;
use js::glue::{
CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps,
RUST_js_GetErrorMessage, SetBuildId, StreamConsumerConsumeChunk,
@@ -27,23 +29,23 @@ use js::glue::{
use js::jsapi::{
AsmJSOption, BuildIdCharVector, ContextOptionsRef, DisableIncrementalGC,
Dispatchable as JSRunnable, Dispatchable_MaybeShuttingDown, GCDescription, GCOptions,
- GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, Heap,
+ GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, HandleString, Heap,
InitConsumeStreamCallback, InitDispatchToEventLoop, JSContext as RawJSContext, JSGCParamKey,
JSGCStatus, JSJitCompilerOption, JSObject, JSSecurityCallbacks, JSTracer,
JS_AddExtraGCRootsTracer, JS_InitDestroyPrincipalsCallback, JS_InitReadPrincipalsCallback,
JS_RequestInterruptCallback, JS_SetGCCallback, JS_SetGCParameter,
JS_SetGlobalJitCompilerOption, JS_SetOffthreadIonCompilationEnabled,
JS_SetParallelParsingEnabled, JS_SetSecurityCallbacks, JobQueue, MimeType,
- PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, SetDOMCallbacks,
- SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks, SetProcessBuildIdOp,
- SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer,
+ PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, RuntimeCode,
+ SetDOMCallbacks, SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks,
+ SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer,
};
use js::jsval::UndefinedValue;
use js::panic::wrap_panic;
use js::rust::wrappers::{GetPromiseIsHandled, JS_GetPromiseResult};
use js::rust::{
- Handle, HandleObject as RustHandleObject, IntoHandle, JSEngine, JSEngineHandle, ParentRuntime,
- Runtime as RustRuntime,
+ describe_scripted_caller, Handle, HandleObject as RustHandleObject, IntoHandle, JSEngine,
+ JSEngineHandle, ParentRuntime, Runtime as RustRuntime,
};
use lazy_static::lazy_static;
use malloc_size_of::MallocSizeOfOps;
@@ -79,6 +81,7 @@ use crate::microtask::{EnqueuedPromiseCallback, Microtask, MicrotaskQueue};
use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_module::EnsureModuleHooksInitialized;
use crate::script_thread::trace_thread;
+use crate::security_manager::CSPViolationReporter;
use crate::task::TaskBox;
use crate::task_source::networking::NetworkingTaskSource;
use crate::task_source::{TaskSource, TaskSourceName};
@@ -90,8 +93,7 @@ static JOB_QUEUE_TRAPS: JobQueueTraps = JobQueueTraps {
};
static SECURITY_CALLBACKS: JSSecurityCallbacks = JSSecurityCallbacks {
- // TODO: Content Security Policy <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>
- contentSecurityPolicyAllows: None,
+ contentSecurityPolicyAllows: Some(content_security_policy_allows),
subsumes: Some(principals::subsumes),
};
@@ -311,6 +313,61 @@ unsafe extern "C" fn promise_rejection_tracker(
})
}
+#[allow(unsafe_code)]
+unsafe extern "C" fn content_security_policy_allows(
+ cx: *mut RawJSContext,
+ runtime_code: RuntimeCode,
+ sample: HandleString,
+) -> bool {
+ let mut allowed = false;
+ let cx = JSContext::from_ptr(cx);
+ wrap_panic(&mut || {
+ // SpiderMonkey provides null pointer when executing webassembly.
+ let sample = match sample {
+ sample if !sample.is_null() => Some(jsstr_to_string(*cx, *sample)),
+ _ => None,
+ };
+ let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
+ let global = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
+ let Some(csp_list) = global.get_csp_list() else {
+ allowed = true;
+ return;
+ };
+
+ let is_js_evaluation_allowed = csp_list.is_js_evaluation_allowed() == CheckResult::Allowed;
+ let is_wasm_evaluation_allowed =
+ csp_list.is_wasm_evaluation_allowed() == CheckResult::Allowed;
+ let scripted_caller = describe_scripted_caller(*cx).unwrap_or_default();
+
+ allowed = match runtime_code {
+ RuntimeCode::JS if is_js_evaluation_allowed => true,
+ RuntimeCode::WASM if is_wasm_evaluation_allowed => true,
+ _ => false,
+ };
+
+ if !allowed {
+ // FIXME: Don't fire event if `script-src` and `default-src`
+ // were not passed.
+ for policy in csp_list.0 {
+ let task = CSPViolationReporter::new(
+ &global,
+ sample.clone(),
+ policy.disposition == PolicyDisposition::Report,
+ runtime_code,
+ scripted_caller.filename.clone(),
+ scripted_caller.line,
+ scripted_caller.col,
+ );
+ global
+ .dom_manipulation_task_source()
+ .queue(task, &global)
+ .unwrap();
+ }
+ }
+ });
+ allowed
+}
+
#[allow(unsafe_code, crown::unrooted_must_root)]
/// <https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises>
pub fn notify_about_rejected_promises(global: &GlobalScope) {
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 9427f52a959..85ece3d025c 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -3672,6 +3672,8 @@ impl ScriptThread {
.and_then(|h| h.typed_get::<ReferrerPolicyHeader>())
.map(ReferrerPolicy::from);
+ let status_code = metadata.status.map(|status| status.0).unwrap_or(200);
+
let document = Document::new(
&window,
HasBrowsingContext::Yes,
@@ -3685,6 +3687,7 @@ impl ScriptThread {
loader,
referrer,
referrer_policy,
+ Some(status_code),
incomplete.canceller,
);
document.set_ready_state(DocumentReadyState::Loading);
diff --git a/components/script/security_manager.rs b/components/script/security_manager.rs
new file mode 100644
index 00000000000..42795895315
--- /dev/null
+++ b/components/script/security_manager.rs
@@ -0,0 +1,177 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use js::jsapi::RuntimeCode;
+use net_traits::request::Referrer;
+use serde::Serialize;
+use servo_atoms::Atom;
+use servo_url::ServoUrl;
+
+use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit;
+use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding::{
+ SecurityPolicyViolationEventDisposition, SecurityPolicyViolationEventInit,
+};
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::refcounted::Trusted;
+use crate::dom::bindings::reflector::DomObject;
+use crate::dom::event::{Event, EventBubbles, EventCancelable};
+use crate::dom::eventtarget::EventTarget;
+use crate::dom::securitypolicyviolationevent::SecurityPolicyViolationEvent;
+use crate::dom::types::GlobalScope;
+use crate::task::TaskOnce;
+
+pub struct CSPViolationReporter {
+ sample: Option<String>,
+ filename: String,
+ report_only: bool,
+ runtime_code: RuntimeCode,
+ line_number: u32,
+ column_number: u32,
+ target: Trusted<EventTarget>,
+}
+
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SecurityPolicyViolationReport {
+ sample: Option<String>,
+ #[serde(rename = "blockedURL")]
+ blocked_url: String,
+ referrer: String,
+ status_code: u16,
+ #[serde(rename = "documentURL")]
+ document_url: String,
+ source_file: String,
+ violated_directive: String,
+ effective_directive: String,
+ line_number: u32,
+ column_number: u32,
+ original_policy: String,
+ disposition: SecurityPolicyViolationEventDisposition,
+}
+
+impl CSPViolationReporter {
+ pub fn new(
+ global: &GlobalScope,
+ sample: Option<String>,
+ report_only: bool,
+ runtime_code: RuntimeCode,
+ filename: String,
+ line_number: u32,
+ column_number: u32,
+ ) -> CSPViolationReporter {
+ CSPViolationReporter {
+ sample,
+ filename,
+ report_only,
+ runtime_code,
+ line_number,
+ column_number,
+ target: Trusted::new(global.upcast::<EventTarget>()),
+ }
+ }
+
+ fn get_report(&self, global: &GlobalScope) -> SecurityPolicyViolationReport {
+ SecurityPolicyViolationReport {
+ sample: self.sample.clone(),
+ disposition: match self.report_only {
+ true => SecurityPolicyViolationEventDisposition::Report,
+ false => SecurityPolicyViolationEventDisposition::Enforce,
+ },
+ // https://w3c.github.io/webappsec-csp/#violation-resource
+ blocked_url: match self.runtime_code {
+ RuntimeCode::JS => "eval".to_owned(),
+ RuntimeCode::WASM => "wasm-eval".to_owned(),
+ },
+ // https://w3c.github.io/webappsec-csp/#violation-referrer
+ referrer: match global.get_referrer() {
+ Referrer::Client(url) => self.strip_url_for_reports(url),
+ Referrer::ReferrerUrl(url) => self.strip_url_for_reports(url),
+ _ => "".to_owned(),
+ },
+ status_code: global.status_code().unwrap_or(200),
+ document_url: self.strip_url_for_reports(global.get_url()),
+ source_file: self.filename.clone(),
+ violated_directive: "script-src".to_owned(),
+ effective_directive: "script-src".to_owned(),
+ line_number: self.line_number,
+ column_number: self.column_number,
+ original_policy: String::default(),
+ }
+ }
+
+ fn fire_violation_event(&self) {
+ let target = self.target.root();
+ let global = &target.global();
+ let report = self.get_report(global);
+
+ let event = SecurityPolicyViolationEvent::new(
+ global,
+ Atom::from("securitypolicyviolation"),
+ EventBubbles::Bubbles,
+ EventCancelable::Cancelable,
+ &report.into(),
+ );
+
+ event.upcast::<Event>().fire(&target);
+ }
+
+ /// <https://w3c.github.io/webappsec-csp/#strip-url-for-use-in-reports>
+ fn strip_url_for_reports(&self, mut url: ServoUrl) -> String {
+ let scheme = url.scheme();
+ // > Step 1: If url’s scheme is not an HTTP(S) scheme, then return url’s scheme.
+ if scheme != "https" && scheme != "http" {
+ return scheme.to_owned();
+ }
+ // > Step 2: Set url’s fragment to the empty string.
+ url.set_fragment(None);
+ // > Step 3: Set url’s username to the empty string.
+ let _ = url.set_username("");
+ // > Step 4: Set url’s password to the empty string.
+ let _ = url.set_password(None);
+ // > Step 5: Return the result of executing the URL serializer on url.
+ url.into_string()
+ }
+}
+
+/// Corresponds to the operation in 5.5 Report Violation
+/// <https://w3c.github.io/webappsec-csp/#report-violation>
+/// > Queue a task to run the following steps:
+impl TaskOnce for CSPViolationReporter {
+ fn run_once(self) {
+ // > If target implements EventTarget, fire an event named securitypolicyviolation
+ // > that uses the SecurityPolicyViolationEvent interface
+ // > at target with its attributes initialized as follows:
+ self.fire_violation_event();
+ // TODO: Support `report-to` directive that corresponds to 5.5.3.5.
+ }
+}
+
+impl From<SecurityPolicyViolationReport> for SecurityPolicyViolationEventInit {
+ fn from(value: SecurityPolicyViolationReport) -> Self {
+ SecurityPolicyViolationEventInit {
+ sample: value.sample.unwrap_or_default().into(),
+ blockedURI: value.blocked_url.into(),
+ referrer: value.referrer.into(),
+ statusCode: value.status_code,
+ documentURI: value.document_url.into(),
+ sourceFile: value.source_file.into(),
+ violatedDirective: value.violated_directive.into(),
+ effectiveDirective: value.effective_directive.into(),
+ lineNumber: value.line_number,
+ columnNumber: value.column_number,
+ originalPolicy: value.original_policy.into(),
+ disposition: value.disposition.into(),
+ parent: EventInit::empty(),
+ }
+ }
+}
+
+impl Serialize for SecurityPolicyViolationEventDisposition {
+ fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ match self {
+ Self::Report => serializer.serialize_str("report"),
+ Self::Enforce => serializer.serialize_str("enforce"),
+ }
+ }
+}
diff --git a/components/script/timers.rs b/components/script/timers.rs
index 7dabbd5a5fa..98547726c96 100644
--- a/components/script/timers.rs
+++ b/components/script/timers.rs
@@ -442,7 +442,12 @@ impl JsTimers {
) -> i32 {
let callback = match callback {
TimerCallback::StringTimerCallback(code_str) => {
- InternalTimerCallback::StringTimerCallback(code_str)
+ let cx = GlobalScope::get_cx();
+ if global.is_js_evaluation_allowed(cx) {
+ InternalTimerCallback::StringTimerCallback(code_str)
+ } else {
+ return 0;
+ }
},
TimerCallback::FunctionTimerCallback(function) => {
// This is a bit complicated, but this ensures that the vector's
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index 166e2d005f0..4d45e1ed64b 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -9,6 +9,11 @@ skip: true
skip: false
[samesite]
skip: true
+[content-security-policy]
+ [unsafe-eval]
+ skip: false
+ [wasm-unsafe-eval]
+ skip: false
[cors]
skip: false
[css]
diff --git a/tests/wpt/meta/content-security-policy/unsafe-eval/eval-blocked-in-about-blank-iframe.html.ini b/tests/wpt/meta/content-security-policy/unsafe-eval/eval-blocked-in-about-blank-iframe.html.ini
new file mode 100644
index 00000000000..d47972783e3
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/unsafe-eval/eval-blocked-in-about-blank-iframe.html.ini
@@ -0,0 +1,4 @@
+[eval-blocked-in-about-blank-iframe.html]
+ expected: ERROR
+ [eval-blocked-in-about-blank-iframe]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini
new file mode 100644
index 00000000000..e6fefbf0518
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini
@@ -0,0 +1,12 @@
+[default-src-blocks-wasm.any.worker.html]
+ [default-src-blocks-wasm]
+ expected: FAIL
+
+
+[default-src-blocks-wasm.any.html]
+
+[default-src-blocks-wasm.any.serviceworker.html]
+ expected: ERROR
+
+[default-src-blocks-wasm.any.sharedworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-unsafe-eval-allows-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-unsafe-eval-allows-wasm.any.js.ini
new file mode 100644
index 00000000000..4301d110d5e
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-unsafe-eval-allows-wasm.any.js.ini
@@ -0,0 +1,9 @@
+[default-src-unsafe-eval-allows-wasm.any.sharedworker.html]
+ expected: ERROR
+
+[default-src-unsafe-eval-allows-wasm.any.worker.html]
+
+[default-src-unsafe-eval-allows-wasm.any.html]
+
+[default-src-unsafe-eval-allows-wasm.any.serviceworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-wasm-unsafe-eval-allows-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-wasm-unsafe-eval-allows-wasm.any.js.ini
new file mode 100644
index 00000000000..4c8e908dee5
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-wasm-unsafe-eval-allows-wasm.any.js.ini
@@ -0,0 +1,9 @@
+[default-src-wasm-unsafe-eval-allows-wasm.any.worker.html]
+
+[default-src-wasm-unsafe-eval-allows-wasm.any.html]
+
+[default-src-wasm-unsafe-eval-allows-wasm.any.sharedworker.html]
+ expected: ERROR
+
+[default-src-wasm-unsafe-eval-allows-wasm.any.serviceworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini
new file mode 100644
index 00000000000..f21d0ccfb10
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini
@@ -0,0 +1,4 @@
+[postMessage-wasm-module.html]
+ expected: ERROR
+ [Got the expected securitypolicyviolation in the iframe]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini
new file mode 100644
index 00000000000..e5b65e2f659
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini
@@ -0,0 +1,12 @@
+[script-src-blocks-wasm.any.sharedworker.html]
+ expected: ERROR
+
+[script-src-blocks-wasm.any.worker.html]
+ [script-src-blocks-wasm]
+ expected: FAIL
+
+
+[script-src-blocks-wasm.any.html]
+
+[script-src-blocks-wasm.any.serviceworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini
new file mode 100644
index 00000000000..f9ebe61a198
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini
@@ -0,0 +1,16 @@
+[script-src-spv-asynch.any.sharedworker.html]
+ expected: ERROR
+
+[script-src-spv-asynch.any.html]
+ [Securitypolicyviolation event looks like it should]
+ expected: FAIL
+
+
+[script-src-spv-asynch.any.worker.html]
+ expected: TIMEOUT
+ [Securitypolicyviolation event looks like it should]
+ expected: TIMEOUT
+
+
+[script-src-spv-asynch.any.serviceworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-unsafe-eval-allows-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-unsafe-eval-allows-wasm.any.js.ini
new file mode 100644
index 00000000000..7b6abd3df54
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-unsafe-eval-allows-wasm.any.js.ini
@@ -0,0 +1,9 @@
+[script-src-unsafe-eval-allows-wasm.any.sharedworker.html]
+ expected: ERROR
+
+[script-src-unsafe-eval-allows-wasm.any.html]
+
+[script-src-unsafe-eval-allows-wasm.any.worker.html]
+
+[script-src-unsafe-eval-allows-wasm.any.serviceworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-wasm-unsafe-eval-allows-wasm.any.js.ini b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-wasm-unsafe-eval-allows-wasm.any.js.ini
new file mode 100644
index 00000000000..e07762a7c1e
--- /dev/null
+++ b/tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-wasm-unsafe-eval-allows-wasm.any.js.ini
@@ -0,0 +1,9 @@
+[script-src-wasm-unsafe-eval-allows-wasm.any.serviceworker.html]
+ expected: ERROR
+
+[script-src-wasm-unsafe-eval-allows-wasm.any.html]
+
+[script-src-wasm-unsafe-eval-allows-wasm.any.worker.html]
+
+[script-src-wasm-unsafe-eval-allows-wasm.any.sharedworker.html]
+ expected: ERROR
diff --git a/tests/wpt/meta/html/dom/idlharness.https.html.ini b/tests/wpt/meta/html/dom/idlharness.https.html.ini
index 16ad66da7c7..b420542d544 100644
--- a/tests/wpt/meta/html/dom/idlharness.https.html.ini
+++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini
@@ -2002,9 +2002,6 @@
[Document interface: new Document() must inherit property "onwebkitanimationstart" with the proper type]
expected: FAIL
- [Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
- expected: FAIL
-
[Document interface: calling queryCommandIndeterm(DOMString) on documentWithHandlers with too few arguments must throw TypeError]
expected: FAIL
@@ -2017,9 +2014,6 @@
[Window interface: window must inherit property "onwebkitanimationiteration" with the proper type]
expected: FAIL
- [Window interface: attribute onsecuritypolicyviolation]
- expected: FAIL
-
[Window interface: window must inherit property "applicationCache" with the proper type]
expected: FAIL
@@ -2059,9 +2053,6 @@
[Document interface: documentWithHandlers must inherit property "execCommand(DOMString, optional boolean, optional DOMString)" with the proper type]
expected: FAIL
- [Window interface: window must inherit property "onsecuritypolicyviolation" with the proper type]
- expected: FAIL
-
[Window interface: operation print()]
expected: FAIL
@@ -2074,9 +2065,6 @@
[Document interface: attribute all]
expected: FAIL
- [Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type]
- expected: FAIL
-
[Window interface: operation focus()]
expected: FAIL
@@ -2215,9 +2203,6 @@
[Document interface: operation execCommand(DOMString, optional boolean, optional DOMString)]
expected: FAIL
- [Document interface: attribute onsecuritypolicyviolation]
- expected: FAIL
-
[Window interface: attribute menubar]
expected: FAIL
@@ -2314,9 +2299,6 @@
[Window interface: internal [[SetPrototypeOf\]\] method of interface prototype object - setting to a new value via Object.setPrototypeOf should throw a TypeError]
expected: FAIL
- [Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
- expected: FAIL
-
[Document interface: new Document() must inherit property "queryCommandValue(DOMString)" with the proper type]
expected: FAIL
@@ -2892,9 +2874,6 @@
[HTMLElement interface: document.createElement("noscript") must inherit property "autocapitalize" with the proper type]
expected: FAIL
- [HTMLElement interface: attribute onsecuritypolicyviolation]
- expected: FAIL
-
[HTMLTableColElement interface: document.createElement("col") must inherit property "align" with the proper type]
expected: FAIL
@@ -4155,9 +4134,6 @@
[HTMLObjectElement interface: document.createElement("object") must inherit property "data" with the proper type]
expected: FAIL
- [HTMLElement interface: document.createElement("noscript") must inherit property "onsecuritypolicyviolation" with the proper type]
- expected: FAIL
-
[HTMLFrameElement interface: attribute contentDocument]
expected: FAIL
diff --git a/tests/wpt/meta/html/semantics/document-metadata/the-meta-element/pragma-directives/http-equiv-enumerated-ascii-case-insensitive.html.ini b/tests/wpt/meta/html/semantics/document-metadata/the-meta-element/pragma-directives/http-equiv-enumerated-ascii-case-insensitive.html.ini
deleted file mode 100644
index b0ab6944381..00000000000
--- a/tests/wpt/meta/html/semantics/document-metadata/the-meta-element/pragma-directives/http-equiv-enumerated-ascii-case-insensitive.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[http-equiv-enumerated-ascii-case-insensitive.html]
- [keyword content-security-policy]
- expected: FAIL
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html.ini
new file mode 100644
index 00000000000..359885bb37d
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html.ini
@@ -0,0 +1,10 @@
+[code-cache-nonce.html]
+ expected: ERROR
+ [First dynamic import should use nonce=abc]
+ expected: TIMEOUT
+
+ [Second dynamic import should use nonce=def]
+ expected: NOTRUN
+
+ [Third dynamic import should use nonce=ghi]
+ expected: NOTRUN
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js.ini
index ff014ca4c83..1bed20b7797 100644
--- a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js.ini
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js.ini
@@ -1,4 +1,5 @@
[basic.any.html]
+ expected: TIMEOUT
[basic.any.sharedworker.html]
expected: ERROR
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html.ini
new file mode 100644
index 00000000000..1ecf634225f
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html.ini
@@ -0,0 +1,2 @@
+[propagate-nonce-external-classic.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html.ini
new file mode 100644
index 00000000000..849c9b3e60d
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html.ini
@@ -0,0 +1,2 @@
+[propagate-nonce-external-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html.ini
new file mode 100644
index 00000000000..2874543423a
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html.ini
@@ -0,0 +1,2 @@
+[propagate-nonce-inline-classic.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html.ini
new file mode 100644
index 00000000000..cb8c561fb65
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html.ini
@@ -0,0 +1,2 @@
+[propagate-nonce-inline-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini
index 6c4f4e4311b..48c8e4840d1 100644
--- a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini
@@ -1,4 +1,5 @@
[string-compilation-nonce-classic.html]
+ expected: TIMEOUT
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
expected: FAIL
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini
index d01214d8061..0ef4435c360 100644
--- a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini
@@ -1,4 +1,5 @@
[string-compilation-nonce-module.html]
+ expected: TIMEOUT
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
expected: FAIL
diff --git a/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html.ini b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html.ini
new file mode 100644
index 00000000000..e8c2de6a972
--- /dev/null
+++ b/tests/wpt/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html.ini
@@ -0,0 +1,31 @@
+[v8-code-cache.html]
+ expected: ERROR
+ [text/javascript: Run #1]
+ expected: TIMEOUT
+
+ [text/javascript: Run #2]
+ expected: NOTRUN
+
+ [text/javascript: Run #3]
+ expected: NOTRUN
+
+ [text/javascript: Run #4]
+ expected: NOTRUN
+
+ [text/javascript: Run #5]
+ expected: NOTRUN
+
+ [module: Run #1]
+ expected: NOTRUN
+
+ [module: Run #2]
+ expected: NOTRUN
+
+ [module: Run #3]
+ expected: NOTRUN
+
+ [module: Run #4]
+ expected: NOTRUN
+
+ [module: Run #5]
+ expected: NOTRUN
diff --git a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-all-global-events.html.ini b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-all-global-events.html.ini
index bcba06a84cf..6a781a5e0af 100644
--- a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-all-global-events.html.ini
+++ b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-all-global-events.html.ini
@@ -314,9 +314,6 @@
[onsecuritypolicyviolation: the default value must be null]
expected: FAIL
- [onsecuritypolicyviolation: the content attribute must be compiled into a function as the corresponding property]
- expected: FAIL
-
[onseeked: must be on the appropriate locations for GlobalEventHandlers]
expected: FAIL
diff --git a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
index 55b300bcfd8..b57975c29b5 100644
--- a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
+++ b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
@@ -8,9 +8,6 @@
[not shadowed contextrestored (document.body)]
expected: FAIL
- [not shadowed securitypolicyviolation (document.body)]
- expected: FAIL
-
[not shadowed slotchange (document.body)]
expected: FAIL
@@ -44,9 +41,6 @@
[not shadowed contextrestored (document.createElement("body"))]
expected: FAIL
- [not shadowed securitypolicyviolation (document.createElement("body"))]
- expected: FAIL
-
[not shadowed slotchange (document.createElement("body"))]
expected: FAIL
@@ -80,9 +74,6 @@
[not shadowed contextrestored (window)]
expected: FAIL
- [not shadowed securitypolicyviolation (window)]
- expected: FAIL
-
[not shadowed slotchange (window)]
expected: FAIL
diff --git a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-frameset-window.html.ini b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-frameset-window.html.ini
index 8629986643f..d5f481a86a8 100644
--- a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-frameset-window.html.ini
+++ b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-frameset-window.html.ini
@@ -8,9 +8,6 @@
[not shadowed contextrestored (document.body)]
expected: FAIL
- [not shadowed securitypolicyviolation (document.body)]
- expected: FAIL
-
[not shadowed slotchange (document.body)]
expected: FAIL
@@ -44,9 +41,6 @@
[not shadowed contextrestored (document.createElement("frameset"))]
expected: FAIL
- [not shadowed securitypolicyviolation (document.createElement("frameset"))]
- expected: FAIL
-
[not shadowed slotchange (document.createElement("frameset"))]
expected: FAIL
@@ -80,9 +74,6 @@
[not shadowed contextrestored (window)]
expected: FAIL
- [not shadowed securitypolicyviolation (window)]
- expected: FAIL
-
[not shadowed slotchange (window)]
expected: FAIL
diff --git a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html.ini b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html.ini
index adeee7fbca5..1745981a486 100644
--- a/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html.ini
+++ b/tests/wpt/meta/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html.ini
@@ -8,9 +8,6 @@
[contextrestored is unaffected on a windowless body]
expected: FAIL
- [securitypolicyviolation is unaffected on a windowless body]
- expected: FAIL
-
[slotchange is unaffected on a windowless body]
expected: FAIL
@@ -35,9 +32,6 @@
[contextrestored is unaffected on a windowless frameset]
expected: FAIL
- [securitypolicyviolation is unaffected on a windowless frameset]
- expected: FAIL
-
[slotchange is unaffected on a windowless frameset]
expected: FAIL
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index ac5ccbdd47c..ed0714ae18a 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -13434,14 +13434,14 @@
]
],
"interfaces.html": [
- "d4daa95cfe84f1ffd77d0b631e67deb778db5fc3",
+ "2ab9214e53c431e4a599254d4cb498fd75eef4ed",
[
null,
{}
]
],
"interfaces.worker.js": [
- "b1c7b7e9c5c2f21eafdcd27eafe589e654260628",
+ "2782a452ac10b97c4cd4418fb7ba516325a76fab",
[
"mozilla/interfaces.worker.html",
{}
diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html
index d4daa95cfe8..2ab9214e53c 100644
--- a/tests/wpt/mozilla/tests/mozilla/interfaces.html
+++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html
@@ -223,6 +223,7 @@ test_interfaces([
"Request",
"Response",
"Screen",
+ "SecurityPolicyViolationEvent",
"Selection",
"ShadowRoot",
"StaticRange",
diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
index b1c7b7e9c5c..2782a452ac1 100644
--- a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
+++ b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
@@ -55,6 +55,7 @@ test_interfaces([
"ReadableStream",
"Request",
"Response",
+ "SecurityPolicyViolationEvent",
"TextDecoder",
"TextEncoder",
"URL",