diff options
author | Chocolate Pie <106949016+chocolate-pie@users.noreply.github.com> | 2024-08-02 02:26:44 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-01 17:26:44 +0000 |
commit | 92866ab911cb65d09b6b46bc1fb26868854cbafe (patch) | |
tree | 7cb50444580f91ebf55b3a05d2bd638724dd7f93 | |
parent | 2cf207ddc8133f1abb85704d2d0eee9e26b52723 (diff) | |
download | servo-92866ab911cb65d09b6b46bc1fb26868854cbafe.tar.gz servo-92866ab911cb65d09b6b46bc1fb26868854cbafe.zip |
enhance: Add support for `unsafe-eval` and `wasm-unsafe-eval` (#32893)
Signed-off-by: Chocolate Pie <106949016+chocolate-pie@users.noreply.github.com>
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", |