mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Merge 7e61cee526
into 5ef66ce386
This commit is contained in:
commit
8dbcb49906
8 changed files with 133 additions and 60 deletions
|
@ -4299,7 +4299,14 @@ impl Document {
|
|||
}
|
||||
|
||||
pub(crate) fn set_csp_list(&self, csp_list: Option<CspList>) {
|
||||
self.policy_container.borrow_mut().set_csp_list(csp_list);
|
||||
if let Some(new_list) = csp_list {
|
||||
let mut current = self.get_csp_list();
|
||||
match current {
|
||||
Some(ref mut existing) => existing.append(new_list),
|
||||
None => current = Some(new_list),
|
||||
}
|
||||
self.policy_container.borrow_mut().set_csp_list(current);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_csp_list(&self) -> Option<CspList> {
|
||||
|
|
|
@ -2,19 +2,15 @@
|
|||
* 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::{LocalName, Prefix, local_name, ns};
|
||||
use html5ever::{LocalName, Prefix};
|
||||
use js::rust::HandleObject;
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::htmlmetaelement::HTMLMetaElement;
|
||||
use crate::dom::node::{BindContext, Node, NodeTraits, ShadowIncluding};
|
||||
use crate::dom::node::{BindContext, Node};
|
||||
use crate::dom::userscripts::load_script;
|
||||
use crate::dom::virtualmethods::VirtualMethods;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
@ -53,48 +49,6 @@ impl HTMLHeadElement {
|
|||
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||
n
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
|
||||
pub(crate) fn set_content_security_policy(&self) {
|
||||
let doc = self.owner_document();
|
||||
|
||||
if doc.GetHead().as_deref() != Some(self) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut csp_list: Option<CspList> = None;
|
||||
let node = self.upcast::<Node>();
|
||||
let candidates = 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"
|
||||
})
|
||||
.filter(|elem| {
|
||||
elem.get_attribute(&ns!(), &local_name!("content"))
|
||||
.is_some()
|
||||
});
|
||||
|
||||
for meta in candidates {
|
||||
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 {
|
||||
|
|
|
@ -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::{LocalName, Prefix, local_name, ns};
|
||||
use js::rust::HandleObject;
|
||||
|
@ -118,12 +119,47 @@ 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();
|
||||
if parent.downcast::<HTMLHeadElement>().is_some() {
|
||||
self.set_content_security_policy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
|
||||
pub(crate) fn set_content_security_policy(&self) {
|
||||
let doc = self.owner_document();
|
||||
|
||||
let meta_element = self.upcast::<Element>();
|
||||
|
||||
if meta_element
|
||||
.get_string_attribute(&local_name!("http-equiv"))
|
||||
.to_ascii_lowercase() !=
|
||||
*"content-security-policy" ||
|
||||
meta_element
|
||||
.get_attribute(&ns!(), &local_name!("content"))
|
||||
.is_none()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let mut csp_list: Option<CspList> = None;
|
||||
|
||||
if let Some(ref content) = meta_element.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);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps>
|
||||
fn declarative_refresh(&self) {
|
||||
if !self.upcast::<Node>().is_in_a_document_tree() {
|
||||
|
|
|
@ -821,15 +821,7 @@ impl ParserContext {
|
|||
let Some(parser) = self.parser.as_ref().map(|p| p.root()) else {
|
||||
return;
|
||||
};
|
||||
let new_csp_list = match parser.document.get_csp_list() {
|
||||
None => parent_csp_list.clone(),
|
||||
Some(original_csp_list) => {
|
||||
let mut appended_csp_list = original_csp_list.clone();
|
||||
appended_csp_list.append(parent_csp_list.clone());
|
||||
appended_csp_list.to_owned()
|
||||
},
|
||||
};
|
||||
parser.document.set_csp_list(Some(new_csp_list));
|
||||
parser.document.set_csp_list(Some(parent_csp_list.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
18
tests/wpt/meta/MANIFEST.json
vendored
18
tests/wpt/meta/MANIFEST.json
vendored
|
@ -397319,6 +397319,10 @@
|
|||
"062d823228a0bad1ed84fc432a262501e11a7d79",
|
||||
[]
|
||||
],
|
||||
"meta-append-header.html.headers": [
|
||||
"85de8bd415def35ca45c0abf74590cdfa393d0f4",
|
||||
[]
|
||||
],
|
||||
"meta-outside-head.sub.html.sub.headers": [
|
||||
"8e90073147a233a74727a3ba03307c1564dc3224",
|
||||
[]
|
||||
|
@ -572954,6 +572958,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"meta-append-header.html": [
|
||||
"2b95e92fdb72b54b716ac51196acc93afab17f92",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"meta-img-src.html": [
|
||||
"bc7ffd66a70d78c4ae9f2cc19f8c2df70914243d",
|
||||
[
|
||||
|
@ -572968,6 +572979,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"meta-multiple-csp.html": [
|
||||
"f09ead7f3e7588f88aadda68e72b1c9362d59910",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"meta-outside-head.sub.html": [
|
||||
"7a706c2fc5f5d21b76e7f62f224c3ff74c80ba79",
|
||||
[
|
||||
|
|
32
tests/wpt/tests/content-security-policy/meta/meta-append-header.html
vendored
Normal file
32
tests/wpt/tests/content-security-policy/meta/meta-append-header.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<meta http-equiv="Content-Security-Policy" content="img-src 'none'">
|
||||
<script nonce="abc" src="/resources/testharness.js"></script>
|
||||
<script nonce="abc" src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script nonce="abc">
|
||||
promise_test(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = document.createElement("img");
|
||||
img.src = "/content-security-policy/support/fail.png";
|
||||
|
||||
img.onload = () => reject("Image loaded unexpectedly");
|
||||
img.onerror = (e) => resolve()
|
||||
|
||||
document.body.appendChild(img);
|
||||
});
|
||||
}, "dynamic img-src is blocked by meta CSP");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = "../resources/ran.js";
|
||||
|
||||
script.onload = () => reject("Script executed unexpectedly");
|
||||
script.onerror = () => resolve();
|
||||
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}, "script without `abc` nonce is blocked by header CSP");
|
||||
</script>
|
||||
</body>
|
1
tests/wpt/tests/content-security-policy/meta/meta-append-header.html.headers
vendored
Normal file
1
tests/wpt/tests/content-security-policy/meta/meta-append-header.html.headers
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: script-src 'nonce-abc'
|
33
tests/wpt/tests/content-security-policy/meta/meta-multiple-csp.html
vendored
Normal file
33
tests/wpt/tests/content-security-policy/meta/meta-multiple-csp.html
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abc'">
|
||||
<meta http-equiv="Content-Security-Policy" content="img-src 'none'">
|
||||
<script nonce="abc" src="/resources/testharness.js"></script>
|
||||
<script nonce="abc" src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script nonce="abc">
|
||||
promise_test(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = document.createElement("img");
|
||||
img.src = "/content-security-policy/support/fail.png";
|
||||
|
||||
img.onload = () => reject("Image loaded unexpectedly");
|
||||
img.onerror = (e) => resolve()
|
||||
|
||||
document.body.appendChild(img);
|
||||
});
|
||||
}, "dynamic img-src is blocked by meta CSP");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = "../resources/ran.js";
|
||||
|
||||
script.onload = () => reject("Script executed unexpectedly");
|
||||
script.onerror = () => resolve();
|
||||
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}, "script without `abc` nonce is blocked by meta CSP");
|
||||
</script>
|
||||
</body>
|
Loading…
Add table
Add a link
Reference in a new issue