mirror of
https://github.com/servo/servo.git
synced 2025-07-16 11:53:39 +01:00
Check CSP for inline event handlers (#36510)
This also ensures that document now reports all violations and we set the correct directive. With these changes, all `script-src-attr-elem` WPT tests pass. Part of #36437 Requires servo/rust-content-security-policy#3 to land first Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
parent
70b3e24816
commit
2a81987590
64 changed files with 58 additions and 569 deletions
|
@ -4017,13 +4017,18 @@ impl Document {
|
|||
.get_attribute(&ns!(), &local_name!("nonce"))
|
||||
.map(|attr| Cow::Owned(attr.value().to_string())),
|
||||
};
|
||||
// TODO: Instead of ignoring violations, report them.
|
||||
self.get_csp_list()
|
||||
.map(|c| {
|
||||
c.should_elements_inline_type_behavior_be_blocked(&element, type_, source)
|
||||
.0
|
||||
})
|
||||
.unwrap_or(csp::CheckResult::Allowed)
|
||||
let (result, violations) = match self.get_csp_list() {
|
||||
None => {
|
||||
return csp::CheckResult::Allowed;
|
||||
},
|
||||
Some(csp_list) => {
|
||||
csp_list.should_elements_inline_type_behavior_be_blocked(&element, type_, source)
|
||||
},
|
||||
};
|
||||
|
||||
self.global().report_csp_violations(violations);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Prevent any JS or layout from running until the corresponding call to
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::mem;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use content_security_policy as csp;
|
||||
use deny_public_fields::DenyPublicFields;
|
||||
use dom_struct::dom_struct;
|
||||
use fnv::FnvHasher;
|
||||
|
@ -551,9 +552,25 @@ impl EventTarget {
|
|||
url: ServoUrl,
|
||||
line: usize,
|
||||
ty: &str,
|
||||
source: DOMString,
|
||||
source: &str,
|
||||
) {
|
||||
let handler = InternalRawUncompiledHandler { source, line, url };
|
||||
if let Some(element) = self.downcast::<Element>() {
|
||||
let doc = element.owner_document();
|
||||
if doc.should_elements_inline_type_behavior_be_blocked(
|
||||
element.upcast(),
|
||||
csp::InlineCheckType::ScriptAttribute,
|
||||
source,
|
||||
) == csp::CheckResult::Blocked
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let handler = InternalRawUncompiledHandler {
|
||||
source: DOMString::from(source),
|
||||
line,
|
||||
url,
|
||||
};
|
||||
self.set_inline_event_listener(
|
||||
Atom::from(ty),
|
||||
Some(InlineEventListener::Uncompiled(handler)),
|
||||
|
|
|
@ -3450,12 +3450,15 @@ impl GlobalScope {
|
|||
|
||||
pub(crate) fn report_csp_violations(&self, violations: Vec<Violation>) {
|
||||
for violation in violations {
|
||||
let sample = match violation.resource {
|
||||
ViolationResource::Inline { .. } | ViolationResource::Url(_) => None,
|
||||
ViolationResource::TrustedTypePolicy { sample } => Some(sample),
|
||||
let (sample, resource) = match violation.resource {
|
||||
ViolationResource::Inline { .. } => (None, "inline".to_owned()),
|
||||
ViolationResource::Url(url) => (None, url.into()),
|
||||
ViolationResource::TrustedTypePolicy { sample } => {
|
||||
(Some(sample), "trusted-types-policy".to_owned())
|
||||
},
|
||||
};
|
||||
let report = CSPViolationReportBuilder::default()
|
||||
.resource("eval".to_owned())
|
||||
.resource(resource)
|
||||
.sample(sample)
|
||||
.effective_directive(violation.directive.name)
|
||||
.build(self);
|
||||
|
|
|
@ -201,13 +201,14 @@ impl VirtualMethods for HTMLBodyElement {
|
|||
&local_name!("onresize") |
|
||||
&local_name!("onunload") |
|
||||
&local_name!("onerror") => {
|
||||
let source = &**attr.value();
|
||||
let evtarget = window.upcast::<EventTarget>(); // forwarded event
|
||||
let source_line = 1; //TODO(#9604) obtain current JS execution line
|
||||
evtarget.set_event_handler_uncompiled(
|
||||
window.get_url(),
|
||||
source_line,
|
||||
&name[2..],
|
||||
DOMString::from((**attr.value()).to_owned()),
|
||||
source,
|
||||
);
|
||||
false
|
||||
},
|
||||
|
|
|
@ -1084,14 +1084,14 @@ impl VirtualMethods for HTMLElement {
|
|||
let element = self.as_element();
|
||||
match (attr.local_name(), mutation) {
|
||||
(name, AttributeMutation::Set(_)) if name.starts_with("on") => {
|
||||
let source = &**attr.value();
|
||||
let evtarget = self.upcast::<EventTarget>();
|
||||
let source_line = 1; //TODO(#9604) get current JS execution line
|
||||
evtarget.set_event_handler_uncompiled(
|
||||
self.owner_window().get_url(),
|
||||
source_line,
|
||||
&name[2..],
|
||||
// FIXME(ajeffrey): Convert directly from AttrValue to DOMString
|
||||
DOMString::from(&**attr.value()),
|
||||
source,
|
||||
);
|
||||
},
|
||||
(&local_name!("form"), mutation) if self.is_form_associated_custom_element() => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue