Title: [198541] trunk
Revision
198541
Author
[email protected]
Date
2016-03-22 12:08:43 -0700 (Tue, 22 Mar 2016)

Log Message

CSP: Check inline event handlers on each run, not only the first
https://bugs.webkit.org/show_bug.cgi?id=115700
<rdar://problem/24211159>

Reviewed by Andy Estes.

Source/WebCore:

Fixes an issue where an inline event handler would always be allowed to execute if it
executed at least once.

Currently we query whether the Content Security Policy (CSP) of the page permits inline event
handlers each time we register a new handler for an event. And a handler is registered exactly
once the first time the event associated with it is dispatched. Once a handler is registered
as a listener for an event E then we will always invoke the handler when event E is dispatched
regardless of whether the CSP of the page changes (say, as a result of programmatically inserting
a <meta http-equiv="Content-Security-Policy">). Instead we should always check the
CSP of the page whenever we are going to invoke an event handler.

* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent): Check the CSP of the page and bail out if the
policy does not permit execution of an inline event handler.
* bindings/js/JSEventListener.h:
(WebCore::JSEventListener::sourceURL): Added. Default implementation that returns an empty string.
(WebCore::JSEventListener::sourcePosition): Added. Default implementation that returns a default position.
* bindings/js/JSLazyEventListener.cpp:
(WebCore::JSLazyEventListener::JSLazyEventListener): Update code following instance variable
renaming in JSLazyEventListener.h.
(WebCore::JSLazyEventListener::initializeJSFunction): Ditto.
* bindings/js/JSLazyEventListener.h: Override JSEventListener::sourceURL() and JSEventListener::sourcePosition().
Changed all mutable instance variables to immutable ones as we do not modify these variables
in any const member functions. Also renamed instance variable m_position to m_sourcePosition
to better describe that it represents the source code position where the event handler was defined.

LayoutTests:

Update expected result for test http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta.html
and remove its entry from file LayoutTests/TestExpectations now that it passes.

* TestExpectations:
* http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (198540 => 198541)


--- trunk/LayoutTests/ChangeLog	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/LayoutTests/ChangeLog	2016-03-22 19:08:43 UTC (rev 198541)
@@ -1,3 +1,17 @@
+2016-03-22  Daniel Bates  <[email protected]>
+
+        CSP: Check inline event handlers on each run, not only the first
+        https://bugs.webkit.org/show_bug.cgi?id=115700
+        <rdar://problem/24211159>
+
+        Reviewed by Andy Estes.
+
+        Update expected result for test http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta.html
+        and remove its entry from file LayoutTests/TestExpectations now that it passes.
+
+        * TestExpectations:
+        * http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta-expected.txt:
+
 2016-03-22  Ryan Haddad  <[email protected]>
 
         Skipping media/media-document-audio-repaint.html on El Capitan Debug WK2

Modified: trunk/LayoutTests/TestExpectations (198540 => 198541)


--- trunk/LayoutTests/TestExpectations	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/LayoutTests/TestExpectations	2016-03-22 19:08:43 UTC (rev 198541)
@@ -861,7 +861,6 @@
 http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-02.html [ Pass ]
 webkit.org/b/154203 http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/frame-ancestors-overrides-xfo.html
 webkit.org/b/111869 http/tests/security/contentSecurityPolicy/eval-blocked-and-sends-report.html
-webkit.org/b/115700 http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta.html [ Failure ]
 webkit.org/b/153148 http/tests/security/contentSecurityPolicy/eval-allowed-in-report-only-mode-and-sends-report.html
 webkit.org/b/153150 http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load.html
 webkit.org/b/153150 http/tests/security/contentSecurityPolicy/1.1/child-src/frame-fires-load-event-when-blocked.html

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta-expected.txt (198540 => 198541)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta-expected.txt	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/inline-event-handler-blocked-after-injecting-meta-expected.txt	2016-03-22 19:08:43 UTC (rev 198541)
@@ -2,6 +2,6 @@
 CONSOLE MESSAGE: line 21: PASS: Event handler triggered pre-policy.
 CONSOLE MESSAGE: line 14: Injecting Content-Security-Policy.
 CONSOLE MESSAGE: line 19: Clicking a link, post-policy:
-CONSOLE MESSAGE: line 21: Refused to execute inline event handler because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
+CONSOLE MESSAGE: line 21: Refused to execute inline event handler because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
 
 This test checks that CSP is evaluated on each call to an inline event handler, even if it's been executed pre-policy. It passes if one 'PASS' and no 'FAIL' messages appear.

Modified: trunk/Source/WebCore/ChangeLog (198540 => 198541)


--- trunk/Source/WebCore/ChangeLog	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/Source/WebCore/ChangeLog	2016-03-22 19:08:43 UTC (rev 198541)
@@ -1,3 +1,37 @@
+2016-03-22  Daniel Bates  <[email protected]>
+
+        CSP: Check inline event handlers on each run, not only the first
+        https://bugs.webkit.org/show_bug.cgi?id=115700
+        <rdar://problem/24211159>
+
+        Reviewed by Andy Estes.
+
+        Fixes an issue where an inline event handler would always be allowed to execute if it
+        executed at least once.
+
+        Currently we query whether the Content Security Policy (CSP) of the page permits inline event
+        handlers each time we register a new handler for an event. And a handler is registered exactly
+        once the first time the event associated with it is dispatched. Once a handler is registered
+        as a listener for an event E then we will always invoke the handler when event E is dispatched
+        regardless of whether the CSP of the page changes (say, as a result of programmatically inserting
+        a <meta http-equiv="Content-Security-Policy">). Instead we should always check the
+        CSP of the page whenever we are going to invoke an event handler.
+
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::handleEvent): Check the CSP of the page and bail out if the
+        policy does not permit execution of an inline event handler.
+        * bindings/js/JSEventListener.h:
+        (WebCore::JSEventListener::sourceURL): Added. Default implementation that returns an empty string.
+        (WebCore::JSEventListener::sourcePosition): Added. Default implementation that returns a default position.
+        * bindings/js/JSLazyEventListener.cpp:
+        (WebCore::JSLazyEventListener::JSLazyEventListener): Update code following instance variable
+        renaming in JSLazyEventListener.h.
+        (WebCore::JSLazyEventListener::initializeJSFunction): Ditto. 
+        * bindings/js/JSLazyEventListener.h: Override JSEventListener::sourceURL() and JSEventListener::sourcePosition().
+        Changed all mutable instance variables to immutable ones as we do not modify these variables
+        in any const member functions. Also renamed instance variable m_position to m_sourcePosition
+        to better describe that it represents the source code position where the event handler was defined.
+
 2016-03-22  Jer Noble  <[email protected]>
 
         Media elements allowed to play without a user gesture, but requiring fullscreen playback, should not be allowed to autoplay.

Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (198540 => 198541)


--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp	2016-03-22 19:08:43 UTC (rev 198541)
@@ -21,6 +21,7 @@
 #include "JSEventListener.h"
 
 #include "BeforeUnloadEvent.h"
+#include "ContentSecurityPolicy.h"
 #include "Event.h"
 #include "Frame.h"
 #include "HTMLElement.h"
@@ -93,6 +94,8 @@
         JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject);
         if (!window->wrapped().isCurrentlyDisplayedInFrame())
             return;
+        if (wasCreatedFromMarkup() && !scriptExecutionContext->contentSecurityPolicy()->allowInlineEventHandlers(sourceURL(), sourcePosition().m_line))
+            return;
         // FIXME: Is this check needed for other contexts?
         ScriptController& script = window->wrapped().frame()->script();
         if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())

Modified: trunk/Source/WebCore/bindings/js/JSEventListener.h (198540 => 198541)


--- trunk/Source/WebCore/bindings/js/JSEventListener.h	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.h	2016-03-22 19:08:43 UTC (rev 198541)
@@ -26,6 +26,8 @@
 #include <heap/Weak.h>
 #include <heap/WeakInlines.h>
 #include <wtf/Ref.h>
+#include <wtf/text/TextPosition.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -61,6 +63,9 @@
     JSC::JSObject* wrapper() const { return m_wrapper.get(); }
     void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); }
 
+    virtual String sourceURL() const { return String(); }
+    virtual TextPosition sourcePosition() const { return TextPosition::minimumPosition(); }
+
 private:
     virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
     void visitJSFunction(JSC::SlotVisitor&) override;

Modified: trunk/Source/WebCore/bindings/js/JSLazyEventListener.cpp (198540 => 198541)


--- trunk/Source/WebCore/bindings/js/JSLazyEventListener.cpp	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/Source/WebCore/bindings/js/JSLazyEventListener.cpp	2016-03-22 19:08:43 UTC (rev 198541)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2001 Peter Kelly ([email protected])
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2003-2016 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -37,13 +37,13 @@
 
 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, eventListenerCounter, ("JSLazyEventListener"));
 
-JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& position, JSObject* wrapper, DOMWrapperWorld& isolatedWorld)
+JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& sourcePosition, JSObject* wrapper, DOMWrapperWorld& isolatedWorld)
     : JSEventListener(0, wrapper, true, isolatedWorld)
     , m_functionName(functionName)
     , m_eventParameterName(eventParameterName)
     , m_code(code)
     , m_sourceURL(sourceURL)
-    , m_position(position)
+    , m_sourcePosition(sourcePosition)
     , m_originalNode(node)
 {
     // We don't retain the original node because we assume it
@@ -54,8 +54,8 @@
 
     // A JSLazyEventListener can be created with a line number of zero when it is created with
     // a setAttribute call from _javascript_, so make the line number 1 in that case.
-    if (m_position == TextPosition::belowRangePosition())
-        m_position = TextPosition::minimumPosition();
+    if (m_sourcePosition == TextPosition::belowRangePosition())
+        m_sourcePosition = TextPosition::minimumPosition();
 
     ASSERT(m_eventParameterName == "evt" || m_eventParameterName == "event");
 
@@ -87,7 +87,7 @@
     if (!document.frame())
         return nullptr;
 
-    if (!document.contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_position.m_line))
+    if (!document.contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_sourcePosition.m_line))
         return nullptr;
 
     ScriptController& script = document.frame()->script();
@@ -106,11 +106,11 @@
 
     // We want all errors to refer back to the line on which our attribute was
     // declared, regardless of any newlines in our _javascript_ source text.
-    int overrideLineNumber = m_position.m_line.oneBasedInt();
+    int overrideLineNumber = m_sourcePosition.m_line.oneBasedInt();
 
     JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(
         exec, exec->lexicalGlobalObject(), args, Identifier::fromString(exec, m_functionName),
-        m_sourceURL, m_position, overrideLineNumber);
+        m_sourceURL, m_sourcePosition, overrideLineNumber);
 
     if (exec->hadException()) {
         reportCurrentException(exec);

Modified: trunk/Source/WebCore/bindings/js/JSLazyEventListener.h (198540 => 198541)


--- trunk/Source/WebCore/bindings/js/JSLazyEventListener.h	2016-03-22 18:28:53 UTC (rev 198540)
+++ trunk/Source/WebCore/bindings/js/JSLazyEventListener.h	2016-03-22 19:08:43 UTC (rev 198541)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2001 Peter Kelly ([email protected])
- *  Copyright (C) 2003, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -21,8 +21,6 @@
 #define JSLazyEventListener_h
 
 #include "JSEventListener.h"
-#include <wtf/text/TextPosition.h>
-#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -40,6 +38,9 @@
 
     virtual ~JSLazyEventListener();
 
+    String sourceURL() const final { return m_sourceURL; }
+    TextPosition sourcePosition() const final { return m_sourcePosition; }
+
 private:
     struct CreationArguments;
     static RefPtr<JSLazyEventListener> create(const CreationArguments&);
@@ -49,11 +50,11 @@
     JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const override;
     bool wasCreatedFromMarkup() const override { return true; }
 
-    mutable String m_functionName;
-    mutable String m_eventParameterName;
-    mutable String m_code;
-    mutable String m_sourceURL;
-    TextPosition m_position;
+    String m_functionName;
+    String m_eventParameterName;
+    String m_code;
+    String m_sourceURL;
+    TextPosition m_sourcePosition;
     ContainerNode* m_originalNode;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to