Title: [126947] trunk
Revision
126947
Author
[email protected]
Date
2012-08-28 18:16:22 -0700 (Tue, 28 Aug 2012)

Log Message

CSP doesn't turn off eval, etc. in Web Workers
https://bugs.webkit.org/show_bug.cgi?id=93392

Patch by Tom Sepez <[email protected]> on 2012-08-28
Reviewed by Adam Barth.

On the JSC side, the blocking of eval() in workers was handled correctly, so it is
a matter of adding calls check the policy for setTimeout and SetInterval.  On the v8
side, it is a matter of handling the above, plus eval().

Source/WebCore: 

On the v8 side, the v8 context isn't available when the callers want to disable eval.
Rather than creating it earlier, which is problematic, remember the setting in the
WorkerContextExecutionProxy and apply before the next call to its evaluate() method.

Tests: http/tests/security/contentSecurityPolicy/worker-eval-blocked.html
       http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html

* bindings/js/JSWorkerContextCustom.cpp:
(WebCore::JSWorkerContext::setTimeout):
(WebCore::JSWorkerContext::setInterval):
* bindings/v8/WorkerContextExecutionProxy.cpp:
(WebCore::WorkerContextExecutionProxy::WorkerContextExecutionProxy):
(WebCore::WorkerContextExecutionProxy::evaluate):
(WebCore::WorkerContextExecutionProxy::setEvalAllowed):
(WebCore):
* bindings/v8/WorkerContextExecutionProxy.h:
(WorkerContextExecutionProxy):
* bindings/v8/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::disableEval):
* bindings/v8/custom/V8WorkerContextCustom.cpp:
(WebCore::SetTimeoutOrInterval):

LayoutTests: 

* http/tests/security/contentSecurityPolicy/resources/worker-eval.js: Added.
* http/tests/security/contentSecurityPolicy/resources/worker-function-function.js: Added.
(fn):
* http/tests/security/contentSecurityPolicy/resources/worker-set-timeout.js:
* http/tests/security/contentSecurityPolicy/worker-eval-blocked-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/worker-eval-blocked.html: Added.
* http/tests/security/contentSecurityPolicy/worker-function-function-blocked-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html: Added.
* http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (126946 => 126947)


--- trunk/LayoutTests/ChangeLog	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/LayoutTests/ChangeLog	2012-08-29 01:16:22 UTC (rev 126947)
@@ -1,3 +1,24 @@
+2012-08-28  Tom Sepez  <[email protected]>
+
+        CSP doesn't turn off eval, etc. in Web Workers
+        https://bugs.webkit.org/show_bug.cgi?id=93392
+
+        Reviewed by Adam Barth.
+
+        On the JSC side, the blocking of eval() in workers was handled correctly, so it is
+        a matter of adding calls check the policy for setTimeout and SetInterval.  On the v8
+        side, it is a matter of handling the above, plus eval().
+
+        * http/tests/security/contentSecurityPolicy/resources/worker-eval.js: Added.
+        * http/tests/security/contentSecurityPolicy/resources/worker-function-function.js: Added.
+        (fn):
+        * http/tests/security/contentSecurityPolicy/resources/worker-set-timeout.js:
+        * http/tests/security/contentSecurityPolicy/worker-eval-blocked-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/worker-eval-blocked.html: Added.
+        * http/tests/security/contentSecurityPolicy/worker-function-function-blocked-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html: Added.
+        * http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt:
+
 2012-08-28  Aaron Colwell  <[email protected]>
 
         Make MediaSource event dispatch asynchronous.

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-eval.js (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-eval.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-eval.js	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,7 @@
+var id = 0;
+try {
+  id = eval("1 + 2 + 3");
+}
+catch (e) {
+}
+postMessage(id === 0 ? "eval blocked" : "eval allowed");

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-function-function.js (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-function-function.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-function-function.js	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,9 @@
+var fn = function() {
+    postMessage('Function() function blocked');
+}
+try {
+    fn = new Function("", "postMessage('Function() function allowed');"); 
+}
+catch(e) {
+}
+fn();

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-set-timeout.js (126946 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-set-timeout.js	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker-set-timeout.js	2012-08-29 01:16:22 UTC (rev 126947)
@@ -1,6 +1,6 @@
 var id = 0;
 try {
-    id = 17;  // Test not yet fully enabled.  Simply pretend that a call to setTimeout() here worked.
+    id = setTimeout("postMessage('handler invoked')", 100);
 } catch(e) {
 }
-postMessage(id === 0 ? "setTimeout blocked" : "setTimout allowed");
+postMessage(id === 0 ? "setTimeout blocked" : "setTimeout allowed");

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked-expected.txt (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked-expected.txt	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,2 @@
+ALERT: eval blocked
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked.html (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-eval-blocked.html	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-WebKit-CSP" content="script-src 'self' 'unsafe-inline'"/>
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+</script>
+</head>
+<body>
+<script>
+try {
+    var worker = new Worker('http://127.0.0.1:8000/security/contentSecurityPolicy/resources/worker-eval.js');
+    worker._onmessage_ = function (event) {
+        alert(event.data);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    };
+} catch (e) {
+    alert(e);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked-expected.txt (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked-expected.txt	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,2 @@
+ALERT: Function() function blocked
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html (0 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html	2012-08-29 01:16:22 UTC (rev 126947)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-WebKit-CSP" content="script-src 'self' 'unsafe-inline'"/>
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+</script>
+</head>
+<body>
+<script>
+try {
+    var worker = new Worker('http://127.0.0.1:8000/security/contentSecurityPolicy/resources/worker-function-function.js');
+    worker._onmessage_ = function (event) {
+        alert(event.data);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    };
+} catch (e) {
+    alert(e);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt (126946 => 126947)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt	2012-08-29 01:16:22 UTC (rev 126947)
@@ -1,2 +1,4 @@
-ALERT: setTimout allowed
+CONSOLE MESSAGE: Refused to evaluate script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'".
 
+ALERT: setTimeout blocked
+

Modified: trunk/Source/WebCore/ChangeLog (126946 => 126947)


--- trunk/Source/WebCore/ChangeLog	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/ChangeLog	2012-08-29 01:16:22 UTC (rev 126947)
@@ -1,3 +1,36 @@
+2012-08-28  Tom Sepez  <[email protected]>
+
+        CSP doesn't turn off eval, etc. in Web Workers
+        https://bugs.webkit.org/show_bug.cgi?id=93392
+
+        Reviewed by Adam Barth.
+
+        On the JSC side, the blocking of eval() in workers was handled correctly, so it is
+        a matter of adding calls check the policy for setTimeout and SetInterval.  On the v8
+        side, it is a matter of handling the above, plus eval().
+
+        On the v8 side, the v8 context isn't available when the callers want to disable eval.
+        Rather than creating it earlier, which is problematic, remember the setting in the
+        WorkerContextExecutionProxy and apply before the next call to its evaluate() method.
+
+        Tests: http/tests/security/contentSecurityPolicy/worker-eval-blocked.html
+               http/tests/security/contentSecurityPolicy/worker-function-function-blocked.html
+
+        * bindings/js/JSWorkerContextCustom.cpp:
+        (WebCore::JSWorkerContext::setTimeout):
+        (WebCore::JSWorkerContext::setInterval):
+        * bindings/v8/WorkerContextExecutionProxy.cpp:
+        (WebCore::WorkerContextExecutionProxy::WorkerContextExecutionProxy):
+        (WebCore::WorkerContextExecutionProxy::evaluate):
+        (WebCore::WorkerContextExecutionProxy::setEvalAllowed):
+        (WebCore):
+        * bindings/v8/WorkerContextExecutionProxy.h:
+        (WorkerContextExecutionProxy):
+        * bindings/v8/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::disableEval):
+        * bindings/v8/custom/V8WorkerContextCustom.cpp:
+        (WebCore::SetTimeoutOrInterval):
+
 2012-08-28  Aaron Colwell  <[email protected]>
 
         Make MediaSource event dispatch asynchronous.

Modified: trunk/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp (126946 => 126947)


--- trunk/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp	2012-08-29 01:16:22 UTC (rev 126947)
@@ -122,20 +122,22 @@
 
 JSValue JSWorkerContext::setTimeout(ExecState* exec)
 {
-    // FIXME: Should we enforce a Content-Security-Policy on workers?
-    OwnPtr<ScheduledAction> action = "" currentWorld(exec), 0);
+    OwnPtr<ScheduledAction> action = "" currentWorld(exec), impl()->contentSecurityPolicy());
     if (exec->hadException())
         return jsUndefined();
+    if (!action)
+        return jsNumber(0);
     int delay = exec->argument(1).toInt32(exec);
     return jsNumber(impl()->setTimeout(action.release(), delay));
 }
 
 JSValue JSWorkerContext::setInterval(ExecState* exec)
 {
-    // FIXME: Should we enforce a Content-Security-Policy on workers?
-    OwnPtr<ScheduledAction> action = "" currentWorld(exec), 0);
+    OwnPtr<ScheduledAction> action = "" currentWorld(exec), impl()->contentSecurityPolicy());
     if (exec->hadException())
         return jsUndefined();
+    if (!action)
+        return jsNumber(0);
     int delay = exec->argument(1).toInt32(exec);
     return jsNumber(impl()->setInterval(action.release(), delay));
 }

Modified: trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp (126946 => 126947)


--- trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp	2012-08-29 01:16:22 UTC (rev 126947)
@@ -86,6 +86,7 @@
 
 WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext)
     : m_workerContext(workerContext)
+    , m_disableEvalPending(false)
 {
     initIsolate();
 }
@@ -209,6 +210,11 @@
     if (!initializeIfNeeded())
         return ScriptValue();
 
+    if (m_disableEvalPending) {
+        m_context->AllowCodeGenerationFromStrings(false);
+        m_disableEvalPending = false;
+    }
+
     v8::Context::Scope scope(m_context);
 
     v8::TryCatch exceptionCatcher;
@@ -243,6 +249,11 @@
     return ScriptValue(result);
 }
 
+void WorkerContextExecutionProxy::setEvalAllowed(bool enable)
+{
+    m_disableEvalPending = !enable;
+}
+
 v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Script> script)
 {
     if (script.IsEmpty())

Modified: trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.h (126946 => 126947)


--- trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.h	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.h	2012-08-29 01:16:22 UTC (rev 126947)
@@ -68,6 +68,9 @@
         // events and releases references to their event targets: WorkerContext.
         void trackEvent(Event*);
 
+        // Alow use of eval() and is equivalents in scripts.
+        void setEvalAllowed(bool enable);
+
         // Evaluate a script file in the current execution environment.
         ScriptValue evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerContextExecutionState*);
 
@@ -94,6 +97,8 @@
         Vector<Event*> m_events;
 
         OwnPtr<V8PerContextData> m_perContextData;
+
+        bool m_disableEvalPending;
     };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/WorkerScriptController.cpp (126946 => 126947)


--- trunk/Source/WebCore/bindings/v8/WorkerScriptController.cpp	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/bindings/v8/WorkerScriptController.cpp	2012-08-29 01:16:22 UTC (rev 126947)
@@ -134,6 +134,7 @@
 
 void WorkerScriptController::disableEval()
 {
+    m_proxy->setEvalAllowed(false);
 }
 
 void WorkerScriptController::setException(const ScriptValue& exception)

Modified: trunk/Source/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp (126946 => 126947)


--- trunk/Source/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp	2012-08-29 01:07:56 UTC (rev 126946)
+++ trunk/Source/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp	2012-08-29 01:16:22 UTC (rev 126947)
@@ -33,9 +33,12 @@
 #if ENABLE(WORKERS)
 #include "V8WorkerContext.h"
 
+#include "ContentSecurityPolicy.h"
 #include "DOMTimer.h"
 #include "ExceptionCode.h"
 #include "ScheduledAction.h"
+#include "ScriptCallStack.h"
+#include "ScriptCallStackFactory.h"
 #include "V8Binding.h"
 #include "V8Utilities.h"
 #include "V8WorkerContextEventListener.h"
@@ -63,6 +66,11 @@
 
     v8::Handle<v8::Context> v8Context = proxy->context();
     if (function->IsString()) {
+        if (ContentSecurityPolicy* policy = workerContext->contentSecurityPolicy()) {
+            RefPtr<ScriptCallStack> callStack = createScriptCallStackForInspector();
+            if (!policy->allowEval(callStack.release()))
+                return v8Integer(0, args.GetIsolate());
+        }
         WTF::String stringFunction = toWebCoreString(function);
         timerId = DOMTimer::install(workerContext, adoptPtr(new ScheduledAction(v8Context, stringFunction, workerContext->url())), timeout, singleShot);
     } else if (function->IsFunction()) {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to