mirror of
https://github.com/servo/servo.git
synced 2025-07-19 13:23:46 +01:00
Fix reporting when only the report-only CSP header is present (#38002)
This was a bit confusing at first, but the report-only only had an effect if it was used in conjunction with the regular CSP header. This is incorrect, as the report-only header can be present on its own. Additionally, there was double-logic for parsing the CSP list values, since we can only concatenate CSP lists if we have an initial value, which requires a concrete policy value. Therefore, abstract that way by looping over both headers and handling the case where initially it is `None` and, if the CSP header is not present, still `None` when we parse the `report-only` header. Additionally, update a WPT test. It was expecting the image to load, yet was showing the fail image. Part of #4577 Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
parent
9b5b26386c
commit
2c116f4011
15 changed files with 48 additions and 124 deletions
|
@ -13,7 +13,7 @@ use content_security_policy::{
|
|||
CheckResult, CspList, Destination, Element as CspElement, Initiator, NavigationCheckType,
|
||||
Origin, ParserMetadata, PolicyDisposition, PolicySource, Request, ViolationResource,
|
||||
};
|
||||
use http::HeaderMap;
|
||||
use http::header::{HeaderMap, HeaderValue, ValueIter};
|
||||
use hyper_serde::Serde;
|
||||
use js::rust::describe_scripted_caller;
|
||||
|
||||
|
@ -233,6 +233,9 @@ impl GlobalCspReporting for GlobalScope {
|
|||
element: Option<&Element>,
|
||||
source_position: Option<SourcePosition>,
|
||||
) {
|
||||
if violations.is_empty() {
|
||||
return;
|
||||
}
|
||||
let source_position =
|
||||
source_position.unwrap_or_else(compute_scripted_caller_source_position);
|
||||
for violation in violations {
|
||||
|
@ -297,35 +300,43 @@ impl GlobalCspReporting for GlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/CSP/#initialize-document-csp>
|
||||
pub(crate) fn parse_csp_list_from_metadata(headers: &Option<Serde<HeaderMap>>) -> Option<CspList> {
|
||||
// TODO: Implement step 1 (local scheme special case)
|
||||
let headers = headers.as_ref()?;
|
||||
let mut csp = headers.get_all("content-security-policy").iter();
|
||||
// This silently ignores the CSP if it contains invalid Unicode.
|
||||
// We should probably report an error somewhere.
|
||||
let c = csp.next().and_then(|c| c.to_str().ok())?;
|
||||
let mut csp_list = CspList::parse(c, PolicySource::Header, PolicyDisposition::Enforce);
|
||||
for c in csp {
|
||||
let c = c.to_str().ok()?;
|
||||
csp_list.append(CspList::parse(
|
||||
c,
|
||||
PolicySource::Header,
|
||||
PolicyDisposition::Enforce,
|
||||
));
|
||||
fn parse_and_potentially_append_to_csp_list(
|
||||
old_csp_list: Option<CspList>,
|
||||
csp_header_iter: ValueIter<HeaderValue>,
|
||||
disposition: PolicyDisposition,
|
||||
) -> Option<CspList> {
|
||||
let mut csp_list = old_csp_list;
|
||||
for header in csp_header_iter {
|
||||
// This silently ignores the CSP if it contains invalid Unicode.
|
||||
// We should probably report an error somewhere.
|
||||
let new_csp_list = header
|
||||
.to_str()
|
||||
.ok()
|
||||
.map(|value| CspList::parse(value, PolicySource::Header, disposition));
|
||||
if let Some(new_csp_list_value) = new_csp_list {
|
||||
match csp_list {
|
||||
None => csp_list = Some(new_csp_list_value),
|
||||
Some(ref mut csp_list) => csp_list.append(new_csp_list_value),
|
||||
};
|
||||
}
|
||||
}
|
||||
let csp_report = headers
|
||||
.get_all("content-security-policy-report-only")
|
||||
.iter();
|
||||
// This silently ignores the CSP if it contains invalid Unicode.
|
||||
// We should probably report an error somewhere.
|
||||
for c in csp_report {
|
||||
let c = c.to_str().ok()?;
|
||||
csp_list.append(CspList::parse(
|
||||
c,
|
||||
PolicySource::Header,
|
||||
PolicyDisposition::Report,
|
||||
));
|
||||
}
|
||||
Some(csp_list)
|
||||
csp_list
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/CSP/#parse-response-csp>
|
||||
pub(crate) fn parse_csp_list_from_metadata(headers: &Option<Serde<HeaderMap>>) -> Option<CspList> {
|
||||
let headers = headers.as_ref()?;
|
||||
let csp_enforce_list = parse_and_potentially_append_to_csp_list(
|
||||
None,
|
||||
headers.get_all("content-security-policy").iter(),
|
||||
PolicyDisposition::Enforce,
|
||||
);
|
||||
|
||||
parse_and_potentially_append_to_csp_list(
|
||||
csp_enforce_list,
|
||||
headers
|
||||
.get_all("content-security-policy-report-only")
|
||||
.iter(),
|
||||
PolicyDisposition::Report,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue