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()) {