Implement nonce attribute to pass more CSP checks (#35876)

* Add doc comments to RequestBuilder fields/methods

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Implement Request::cryptographic_nonce_metadata

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Implement HTMLOrSVGElement::nonce

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Set request cryptographic nonce metadata for link elements

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Set request's cryptographic nonce when fetching scripts

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Forward request nonce to rust-content-security-policy

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Update WPT expectations

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-03-10 10:25:34 +01:00 committed by GitHub
parent ce4ba30992
commit 1b6b21cb85
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 111 additions and 289 deletions

View file

@ -641,6 +641,14 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
Ok(internals)
}
// FIXME: The nonce should be stored in an internal slot instead of an
// attribute (https://html.spec.whatwg.org/multipage/#cryptographicnonce)
// https://html.spec.whatwg.org/multipage/#dom-noncedelement-nonce
make_getter!(Nonce, "nonce");
// https://html.spec.whatwg.org/multipage/#dom-noncedelement-nonce
make_setter!(SetNonce, "nonce");
// https://html.spec.whatwg.org/multipage/#dom-fe-autofocus
fn Autofocus(&self) -> bool {
self.element.has_attribute(&local_name!("autofocus"))

View file

@ -30,11 +30,11 @@ use style::parser::ParserContext as CssParserContext;
use style::stylesheets::{CssRuleType, Origin, Stylesheet, UrlExtraData};
use style_traits::ParsingMode;
use super::types::{EventTarget, GlobalScope};
use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenList_Binding::DOMTokenListMethods;
use crate::dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
use crate::dom::bindings::codegen::GenericBindings::HTMLElementBinding::HTMLElement_Binding::HTMLElementMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal;
@ -52,6 +52,7 @@ use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::{BindContext, Node, NodeTraits, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::stylesheet::StyleSheet as DOMStyleSheet;
use crate::dom::types::{EventTarget, GlobalScope};
use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::create_a_potential_cors_request;
use crate::links::LinkRelations;
@ -74,6 +75,7 @@ struct LinkProcessingOptions {
destination: Option<Destination>,
integrity: String,
link_type: String,
cryptographic_nonce_metadata: String,
cross_origin: Option<CorsSettings>,
referrer_policy: ReferrerPolicy,
policy_container: PolicyContainer,
@ -324,6 +326,7 @@ impl HTMLLinkElement {
destination: Some(destination),
integrity: String::new(),
link_type: String::new(),
cryptographic_nonce_metadata: self.upcast::<HTMLElement>().Nonce().into(),
cross_origin: cors_setting_for_element(element),
referrer_policy: referrer_policy_for_element(element),
policy_container: document.policy_container().to_owned(),
@ -651,7 +654,7 @@ impl LinkProcessingOptions {
// url, options's destination, and options's crossorigin.
// Step 6. Set request's policy container to options's policy container.
// Step 7. Set request's integrity metadata to options's integrity.
// FIXME: Step 8. Set request's cryptographic nonce metadata to options's cryptographic nonce metadata.
// Step 8. Set request's cryptographic nonce metadata to options's cryptographic nonce metadata.
// Step 9. Set request's referrer policy to options's referrer policy.
// FIXME: Step 10. Set request's client to options's environment.
// FIXME: Step 11. Set request's priority to options's fetch priority.
@ -667,6 +670,7 @@ impl LinkProcessingOptions {
)
.integrity_metadata(self.integrity)
.policy_container(self.policy_container)
.cryptographic_nonce_metadata(self.cryptographic_nonce_metadata)
.referrer_policy(self.referrer_policy);
// Step 12. Return request.

View file

@ -41,6 +41,7 @@ use crate::dom::attr::Attr;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::GenericBindings::HTMLElementBinding::HTMLElement_Binding::HTMLElementMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal;
@ -582,6 +583,7 @@ pub(crate) fn script_fetch_request(
.parser_metadata(options.parser_metadata)
.integrity_metadata(options.integrity_metadata.clone())
.referrer_policy(options.referrer_policy)
.cryptographic_nonce_metadata(options.cryptographic_nonce)
}
/// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
@ -776,7 +778,7 @@ impl HTMLScriptElement {
// Step 29. Fetch options.
let options = ScriptFetchOptions {
cryptographic_nonce: "".into(),
cryptographic_nonce: self.upcast::<HTMLElement>().Nonce().into(),
integrity_metadata: integrity_metadata.to_owned(),
parser_metadata,
referrer: self.global().get_referrer(),

View file

@ -109,6 +109,10 @@ impl TokenSink for PrefetchSink {
.get_attr(tag, local_name!("integrity"))
.map(|attr| String::from(&attr.value))
.unwrap_or_default();
let cryptographic_nonce = self
.get_attr(tag, local_name!("nonce"))
.map(|attr| String::from(&attr.value))
.unwrap_or_default();
let request = script_fetch_request(
self.webview_id,
url,
@ -119,7 +123,7 @@ impl TokenSink for PrefetchSink {
referrer: self.referrer.clone(),
referrer_policy: self.referrer_policy,
integrity_metadata,
cryptographic_nonce: String::new(),
cryptographic_nonce,
credentials_mode: CredentialsMode::CredentialsSameOrigin,
parser_metadata: ParserMetadata::ParserInserted,
},

View file

@ -5,6 +5,7 @@
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix, local_name, namespace_url, ns};
use js::rust::HandleObject;
use script_bindings::str::DOMString;
use style_dom::ElementState;
use crate::dom::bindings::codegen::Bindings::SVGElementBinding::SVGElementMethods;
@ -81,6 +82,14 @@ impl SVGElementMethods<crate::DomTypeHolder> for SVGElement {
})
}
// FIXME: The nonce should be stored in an internal slot instead of an
// attribute (https://html.spec.whatwg.org/multipage/#cryptographicnonce)
// https://html.spec.whatwg.org/multipage/#dom-noncedelement-nonce
make_getter!(Nonce, "nonce");
// https://html.spec.whatwg.org/multipage/#dom-noncedelement-nonce
make_setter!(SetNonce, "nonce");
// https://html.spec.whatwg.org/multipage/#dom-fe-autofocus
fn Autofocus(&self) -> bool {
self.element.has_attribute(&local_name!("autofocus"))

View file

@ -117,6 +117,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder {
target_webview_id: request.target_webview_id,
redirect_mode: request.redirect_mode,
integrity_metadata: request.integrity_metadata.clone(),
cryptographic_nonce_metadata: request.cryptographic_nonce_metadata.clone(),
url_list: vec![],
parser_metadata: request.parser_metadata,
initiator: request.initiator,