Title: [286860] trunk
Revision
286860
Author
[email protected]
Date
2021-12-10 11:00:44 -0800 (Fri, 10 Dec 2021)

Log Message

LayoutTests/imported/w3c:
CSP: Implement protections against nonce-hijacking
https://bugs.webkit.org/show_bug.cgi?id=233087

Reviewed by Brent Fulgham.

Update expectations.

* web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked-expected.txt:

Source/WebCore:
CSP: Prevent nonce-hijacking
https://bugs.webkit.org/show_bug.cgi?id=233087

Reviewed by Brent Fulgham.

Implement protections against nonce-hijacking as described in this spec:
  https://www.w3.org/TR/CSP3/#security-nonce-hijacking

* dom/Element.cpp:
(WebCore::Element::isNonceable const):
(WebCore::Element::nonce const):
* dom/Element.h:
(WebCore::Element::hasDuplicateAttribute const):
(WebCore::Element::setHasDuplicateAttribute):
* html/parser/AtomHTMLToken.h:
(WebCore::AtomHTMLToken::hasDuplicateAttribute const):
(WebCore::AtomHTMLToken::initializeAttributes):
* html/parser/HTMLConstructionSite.cpp:
(WebCore::setAttributes):
(WebCore::HTMLConstructionSite::insertCustomElement):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (286859 => 286860)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-12-10 19:00:44 UTC (rev 286860)
@@ -1,3 +1,14 @@
+2021-12-10  Patrick Griffis  <[email protected]>
+
+        CSP: Implement protections against nonce-hijacking
+        https://bugs.webkit.org/show_bug.cgi?id=233087
+
+        Reviewed by Brent Fulgham.
+
+        Update expectations.
+
+        * web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked-expected.txt:
+
 2021-12-10  Chris Dumez  <[email protected]>
 
         Radio buttons with no form owner are not grouped

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked-expected.txt (286859 => 286860)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked-expected.txt	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked-expected.txt	2021-12-10 19:00:44 UTC (rev 286860)
@@ -1,3 +1,3 @@
 
-FAIL Unnonced scripts generate reports. assert_unreached: '<script' attribute, no execution. Reached unreachable code
+PASS Unnonced scripts generate reports.
 

Modified: trunk/Source/WebCore/ChangeLog (286859 => 286860)


--- trunk/Source/WebCore/ChangeLog	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/Source/WebCore/ChangeLog	2021-12-10 19:00:44 UTC (rev 286860)
@@ -1,3 +1,26 @@
+2021-12-10  Patrick Griffis  <[email protected]>
+
+        CSP: Prevent nonce-hijacking
+        https://bugs.webkit.org/show_bug.cgi?id=233087
+
+        Reviewed by Brent Fulgham.
+
+        Implement protections against nonce-hijacking as described in this spec:
+          https://www.w3.org/TR/CSP3/#security-nonce-hijacking
+
+        * dom/Element.cpp:
+        (WebCore::Element::isNonceable const):
+        (WebCore::Element::nonce const):
+        * dom/Element.h:
+        (WebCore::Element::hasDuplicateAttribute const):
+        (WebCore::Element::setHasDuplicateAttribute):
+        * html/parser/AtomHTMLToken.h:
+        (WebCore::AtomHTMLToken::hasDuplicateAttribute const):
+        (WebCore::AtomHTMLToken::initializeAttributes):
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::setAttributes):
+        (WebCore::HTMLConstructionSite::insertCustomElement):
+
 2021-12-09  Darin Adler  <[email protected]>
 
         Use simpler idioms for std::less and std::greater possible in modern C++

Modified: trunk/Source/WebCore/dom/Element.cpp (286859 => 286860)


--- trunk/Source/WebCore/dom/Element.cpp	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/Source/WebCore/dom/Element.cpp	2021-12-10 19:00:44 UTC (rev 286860)
@@ -74,6 +74,7 @@
 #include "HTMLOptGroupElement.h"
 #include "HTMLOptionElement.h"
 #include "HTMLParserIdioms.h"
+#include "HTMLScriptElement.h"
 #include "HTMLSelectElement.h"
 #include "HTMLTemplateElement.h"
 #include "IdChangeInvalidation.h"
@@ -109,6 +110,7 @@
 #include "SVGElementTypeHelpers.h"
 #include "SVGNames.h"
 #include "SVGSVGElement.h"
+#include "SVGScriptElement.h"
 #include "ScriptDisallowedScope.h"
 #include "ScrollIntoViewOptions.h"
 #include "ScrollLatchingController.h"
@@ -318,9 +320,40 @@
     return -1;
 }
 
+bool Element::isNonceable() const
+{
+    // https://www.w3.org/TR/CSP3/#is-element-nonceable
+    if (elementRareData()->nonce().isNull())
+        return false;
+
+    if (hasDuplicateAttribute())
+        return false;
+
+    if (hasAttributes()
+        && (is<HTMLScriptElement>(*this) || is<SVGScriptElement>(*this))) {
+        static const char scriptString[] = "<script";
+        static const char styleString[] = "<style";
+
+        for (const auto& attribute : attributesIterator()) {
+            auto name = attribute.localName().convertToASCIILowercase();
+            auto value = attribute.value().convertToASCIILowercase();
+            if (name.contains(scriptString)
+                || name.contains(styleString)
+                || value.contains(scriptString)
+                || value.contains(styleString))
+                return false;
+        }
+    }
+
+    return true;
+}
+
 const AtomString& Element::nonce() const
 {
-    return hasRareData() ? elementRareData()->nonce() : emptyAtom();
+    if (hasRareData() && isNonceable())
+        return elementRareData()->nonce();
+
+    return emptyAtom();
 }
 
 void Element::setNonce(const AtomString& newValue)

Modified: trunk/Source/WebCore/dom/Element.h (286859 => 286860)


--- trunk/Source/WebCore/dom/Element.h	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/Source/WebCore/dom/Element.h	2021-12-10 19:00:44 UTC (rev 286860)
@@ -652,6 +652,9 @@
     String description() const override;
     String debugDescription() const override;
 
+    bool hasDuplicateAttribute() const { return m_hasDuplicateAttribute; };
+    void setHasDuplicateAttribute(bool hasDuplicateAttribute) { m_hasDuplicateAttribute = hasDuplicateAttribute; };
+
 protected:
     Element(const QualifiedName&, Document&, ConstructionType);
 
@@ -688,6 +691,8 @@
     bool isUserActionElementHasFocusVisible() const;
     bool isUserActionElementHasFocusWithin() const;
 
+    bool isNonceable() const;
+
     virtual void didAddUserAgentShadowRoot(ShadowRoot&) { }
 
     void didAddAttribute(const QualifiedName&, const AtomString&);
@@ -765,6 +770,8 @@
 
     QualifiedName m_tagName;
     RefPtr<ElementData> m_elementData;
+
+    bool m_hasDuplicateAttribute { false };
 };
 
 void invalidateForSiblingCombinators(Element* sibling);

Modified: trunk/Source/WebCore/html/parser/AtomHTMLToken.h (286859 => 286860)


--- trunk/Source/WebCore/html/parser/AtomHTMLToken.h	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/Source/WebCore/html/parser/AtomHTMLToken.h	2021-12-10 19:00:44 UTC (rev 286860)
@@ -31,6 +31,8 @@
 
 namespace WebCore {
 
+enum class HasDuplicateAttribute : bool { No, Yes };
+
 class AtomHTMLToken {
 public:
     explicit AtomHTMLToken(HTMLToken&);
@@ -70,6 +72,8 @@
 
     const String& comment() const;
 
+    HasDuplicateAttribute hasDuplicateAttribute() const { return m_hasDuplicateAttribute; };
+
 private:
     HTMLToken::Type m_type;
 
@@ -90,6 +94,8 @@
 
     bool m_selfClosing; // StartTag, EndTag.
     Vector<Attribute> m_attributes; // StartTag, EndTag.
+
+    HasDuplicateAttribute m_hasDuplicateAttribute { HasDuplicateAttribute::No };
 };
 
 const Attribute* findAttribute(const Vector<Attribute>&, const QualifiedName&);
@@ -208,6 +214,8 @@
         // FIXME: This is N^2 for the number of attributes.
         if (!hasAttribute(m_attributes, localName))
             m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), HTMLAtomStringCache::makeAttributeValue(attribute.value)));
+        else
+            m_hasDuplicateAttribute = HasDuplicateAttribute::Yes;
     }
 }
 

Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (286859 => 286860)


--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp	2021-12-10 18:52:08 UTC (rev 286859)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp	2021-12-10 19:00:44 UTC (rev 286860)
@@ -55,16 +55,17 @@
 
 using namespace HTMLNames;
 
-static inline void setAttributes(Element& element, Vector<Attribute>& attributes, ParserContentPolicy parserContentPolicy)
+static inline void setAttributes(Element& element, Vector<Attribute>& attributes, HasDuplicateAttribute hasDuplicateAttribute, ParserContentPolicy parserContentPolicy)
 {
     if (!scriptingContentIsAllowed(parserContentPolicy))
         element.stripScriptingAttributes(attributes);
     element.parserSetAttributes(attributes);
+    element.setHasDuplicateAttribute(hasDuplicateAttribute == HasDuplicateAttribute::Yes);
 }
 
 static inline void setAttributes(Element& element, AtomHTMLToken& token, ParserContentPolicy parserContentPolicy)
 {
-    setAttributes(element, token.attributes(), parserContentPolicy);
+    setAttributes(element, token.attributes(), token.hasDuplicateAttribute(), parserContentPolicy);
 }
 
 static bool hasImpliedEndTag(const HTMLStackItem& item)
@@ -516,7 +517,7 @@
 
 void HTMLConstructionSite::insertCustomElement(Ref<Element>&& element, const AtomString& localName, Vector<Attribute>&& attributes)
 {
-    setAttributes(element, attributes, m_parserContentPolicy);
+    setAttributes(element, attributes, HasDuplicateAttribute::No, m_parserContentPolicy);
     attachLater(currentNode(), element.copyRef());
     m_openElements.push(HTMLStackItem::create(WTFMove(element), localName, WTFMove(attributes)));
     executeQueuedTasks();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to