diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp index f54d99468ff9..3c29d1abf0fc 100644 --- a/dom/base/nsTreeSanitizer.cpp +++ b/dom/base/nsTreeSanitizer.cpp @@ -14,12 +14,14 @@ #include "mozilla/StyleSheetInlines.h" #include "mozilla/UniquePtr.h" #include "mozilla/css/Rule.h" -#include "mozilla/dom/SanitizerBinding.h" #include "mozilla/dom/CSSRuleList.h" #include "mozilla/dom/DocumentFragment.h" -#include "mozilla/dom/ShadowIncludingTreeIterator.h" +#include "mozilla/dom/HTMLFormElement.h" #include "mozilla/dom/HTMLTemplateElement.h" #include "mozilla/dom/HTMLUnknownElement.h" +#include "mozilla/dom/Link.h" +#include "mozilla/dom/SanitizerBinding.h" +#include "mozilla/dom/ShadowIncludingTreeIterator.h" #include "mozilla/dom/SRIMetadata.h" #include "mozilla/NullPrincipal.h" #include "nsAtom.h" @@ -1858,7 +1860,8 @@ void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement, RefPtr attrLocal = attrName->LocalName(); if (mIsForSanitizerAPI) { - if (MustDropAttribute(aElement, attrNs, attrLocal)) { + if (MustDropAttribute(aElement, attrNs, attrLocal) || + MustDropFunkyAttribute(aElement, attrNs, attrLocal)) { aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false); if (mLogRemovals) { LogMessage("Removed unsafe attribute.", aElement->OwnerDoc(), @@ -2045,6 +2048,60 @@ bool nsTreeSanitizer::MustDropAttribute(Element* aElement, return false; } +// https://wicg.github.io/sanitizer-api/#handle-funky-elements +bool nsTreeSanitizer::MustDropFunkyAttribute(Element* aElement, + int32_t aAttrNamespace, + nsAtom* aAttrLocalName) { + // Step 1. If element’s element interface is HTMLTemplateElement: + // Note: This step is implemented in the main loop of SanitizeChildren. + + // Step 2. If element’s element interface has a HTMLHyperlinkElementUtils + // mixin, and if element’s protocol property is "javascript:": + // TODO(https://github.com/WICG/sanitizer-api/issues/168) + if (aAttrLocalName == nsGkAtoms::href) { + if (nsCOMPtr link = do_QueryInterface(aElement)) { + nsCOMPtr uri = link->GetURI(); + if (uri && uri->SchemeIs("javascript")) { + // Step 2.1. Remove the `href` attribute from element. + return true; + } + } + } + + // Step 3. if element’s element interface is HTMLFormElement, and if element’s + // action attribute is a URL with "javascript:" protocol: + if (auto* form = HTMLFormElement::FromNode(aElement)) { + if (aAttrNamespace == kNameSpaceID_None && + aAttrLocalName == nsGkAtoms::action) { + nsCOMPtr uri; + form->GetURIAttr(aAttrLocalName, nullptr, getter_AddRefs(uri)); + if (uri && uri->SchemeIs("javascript")) { + // Step 3.1 Remove the `action` attribute from element. + return true; + } + } + } + + // Step 4. if element’s element interface is HTMLInputElement or + // HTMLButtonElement, and if element’s formaction attribute is a [URL] with + // javascript: protocol + if (aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::button) && + aAttrNamespace == kNameSpaceID_None && + aAttrLocalName == nsGkAtoms::formaction) { + // XXX nsGenericHTMLFormControlElementWithState::GetFormAction falls back to + // the document URI. + nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(aElement); + nsCOMPtr uri; + el->GetURIAttr(aAttrLocalName, nullptr, getter_AddRefs(uri)); + if (uri && uri->SchemeIs("javascript")) { + // Step 4.1 Remove the `formaction` attribute from element. + return true; + } + } + + return false; +} + bool nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement, int32_t aNamespace, nsAtom* aLocalName, bool aFragmentsOnly) { diff --git a/dom/base/nsTreeSanitizer.h b/dom/base/nsTreeSanitizer.h index de9b15ab29bd..8c747c05ffa1 100644 --- a/dom/base/nsTreeSanitizer.h +++ b/dom/base/nsTreeSanitizer.h @@ -205,6 +205,8 @@ class nsTreeSanitizer { // Currently only used for the Sanitizer API. bool MustDropAttribute(mozilla::dom::Element* aElement, int32_t aAttrNamespace, nsAtom* aAttrLocalName); + bool MustDropFunkyAttribute(mozilla::dom::Element* aElement, + int32_t aAttrNamespace, nsAtom* aAttrLocalName); /** * Remove the named URL attribute from the element if the URL fails a diff --git a/testing/web-platform/meta/sanitizer-api/sanitizer-sanitize.https.tentative.html.ini b/testing/web-platform/meta/sanitizer-api/sanitizer-sanitize.https.tentative.html.ini index c1f4e4ba4901..a572c2437f1c 100644 --- a/testing/web-platform/meta/sanitizer-api/sanitizer-sanitize.https.tentative.html.ini +++ b/testing/web-platform/meta/sanitizer-api/sanitizer-sanitize.https.tentative.html.ini @@ -3,71 +3,11 @@ [SanitizerAPI with config: plaintext, sanitize from document function for ] expected: FAIL - [SanitizerAPI with config: HTMLAnchorElement with javascript protocal, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLAnchorElement with javascript protocal start with space, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLAreaElement with javascript protocal, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLAreaElement with javascript protocal start with space, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLFormElement with javascript action, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLFormElement with javascript action start with space, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLInputElement with javascript formaction, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLInputElement with javascript formaction start with space, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLButtonElement with javascript formaction, sanitize from document function for ] - expected: FAIL - - [SanitizerAPI with config: HTMLButtonElement with javascript formaction start with space, sanitize from document function for ] - expected: FAIL - [SanitizerAPI with config: allowAttributes unknown attributes and with allowUnknownMarkup, sanitize from document function for ] expected: FAIL [SanitizerAPI with config: plaintext, sanitize from document fragment function for