Can't use eval in iframes sanbdoxed via CSP header
https://bugs.webkit.org/show_bug.cgi?id=88450
Reviewed by Mihai Parparita.
Source/WebCore:
The initial empty document in a frame inherits the security context of
its parent (including the CSP policy). When we load the real document,
in some cases we'll do a "secure transition" to the new document. That
means that we leave the global object in place in case the parent
document has created any properties that it expects will be visible to
the new document.
If the parent document has a CSP policy that blocks eval, the "no eval"
bit will be set on the global object of the initial document. When we
perform a "secure transition" to the new document, we'll keep the bit,
which is wrong. In this patch, we reset the bit by always enabling
eval when clearing the context, regardless of whether we're performing
a "secure transition".
Test: http/tests/security/contentSecurityPolicy/iframe-inside-csp.html
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::enableEval):
(WebCore):
* bindings/js/ScriptController.h:
(ScriptController):
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::enableEval):
(WebCore):
(WebCore::ScriptController::disableEval):
* bindings/v8/ScriptController.h:
(ScriptController):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::clear):
LayoutTests:
* http/tests/security/contentSecurityPolicy/iframe-inside-csp-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/iframe-inside-csp.html: Added.
* http/tests/security/contentSecurityPolicy/resources/sandboxed-eval.php: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@119913 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index d707121..bff38a9 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2012-06-09 Adam Barth <abarth@webkit.org>
+
+ Can't use eval in iframes sanbdoxed via CSP header
+ https://bugs.webkit.org/show_bug.cgi?id=88450
+
+ Reviewed by Mihai Parparita.
+
+ * http/tests/security/contentSecurityPolicy/iframe-inside-csp-expected.txt: Added.
+ * http/tests/security/contentSecurityPolicy/iframe-inside-csp.html: Added.
+ * http/tests/security/contentSecurityPolicy/resources/sandboxed-eval.php: Added.
+
2012-06-09 Christophe Dumez <christophe.dumez@intel.com>
[EFL] skip new tests added in r119883
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp-expected.txt b/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp-expected.txt
new file mode 100644
index 0000000..a86e993
--- /dev/null
+++ b/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp-expected.txt
@@ -0,0 +1,3 @@
+ALERT: PASS (1/2): Script can execute
+ALERT: PASS (2/2): Eval works
+
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp.html b/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp.html
new file mode 100644
index 0000000..941a3dd
--- /dev/null
+++ b/LayoutTests/http/tests/security/contentSecurityPolicy/iframe-inside-csp.html
@@ -0,0 +1,3 @@
+<meta http-equiv="X-WebKit-CSP" content="script-src 'self'">
+<script src="resources/dump-as-text.js"></script>
+<iframe src="resources/sandboxed-eval.php"></iframe>
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/resources/sandboxed-eval.php b/LayoutTests/http/tests/security/contentSecurityPolicy/resources/sandboxed-eval.php
new file mode 100644
index 0000000..7434f23
--- /dev/null
+++ b/LayoutTests/http/tests/security/contentSecurityPolicy/resources/sandboxed-eval.php
@@ -0,0 +1,10 @@
+<?php
+header("X-WebKit-CSP: sandbox allow-scripts");
+?>
+<script>
+alert('PASS (1/2): Script can execute');
+</script>
+<script>
+eval("alert('PASS (2/2): Eval works')");
+</script>
+Done.
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 033b831..257cf5a 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2012-06-09 Adam Barth <abarth@webkit.org>
+
+ Can't use eval in iframes sanbdoxed via CSP header
+ https://bugs.webkit.org/show_bug.cgi?id=88450
+
+ Reviewed by Mihai Parparita.
+
+ The initial empty document in a frame inherits the security context of
+ its parent (including the CSP policy). When we load the real document,
+ in some cases we'll do a "secure transition" to the new document. That
+ means that we leave the global object in place in case the parent
+ document has created any properties that it expects will be visible to
+ the new document.
+
+ If the parent document has a CSP policy that blocks eval, the "no eval"
+ bit will be set on the global object of the initial document. When we
+ perform a "secure transition" to the new document, we'll keep the bit,
+ which is wrong. In this patch, we reset the bit by always enabling
+ eval when clearing the context, regardless of whether we're performing
+ a "secure transition".
+
+ Test: http/tests/security/contentSecurityPolicy/iframe-inside-csp.html
+
+ * bindings/js/ScriptController.cpp:
+ (WebCore::ScriptController::enableEval):
+ (WebCore):
+ * bindings/js/ScriptController.h:
+ (ScriptController):
+ * bindings/v8/ScriptController.cpp:
+ (WebCore::ScriptController::enableEval):
+ (WebCore):
+ (WebCore::ScriptController::disableEval):
+ * bindings/v8/ScriptController.h:
+ (ScriptController):
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::clear):
+
2012-06-09 Pablo Flouret <pablof@motorola.com>
The value in Access-Control-Allow-Origin is not being matched correctly for CORS-enabled requests
diff --git a/Source/WebCore/bindings/js/ScriptController.cpp b/Source/WebCore/bindings/js/ScriptController.cpp
index fd80a46..7999502 100644
--- a/Source/WebCore/bindings/js/ScriptController.cpp
+++ b/Source/WebCore/bindings/js/ScriptController.cpp
@@ -233,6 +233,14 @@
return TextPosition::minimumPosition();
}
+void ScriptController::enableEval()
+{
+ JSDOMWindowShell* windowShell = existingWindowShell(mainThreadNormalWorld());
+ if (!windowShell)
+ return; // Eval is enabled by default.
+ windowShell->window()->setEvalEnabled(true);
+}
+
void ScriptController::disableEval()
{
windowShell(mainThreadNormalWorld())->window()->setEvalEnabled(false);
diff --git a/Source/WebCore/bindings/js/ScriptController.h b/Source/WebCore/bindings/js/ScriptController.h
index 9e8c28d..0ed9869 100644
--- a/Source/WebCore/bindings/js/ScriptController.h
+++ b/Source/WebCore/bindings/js/ScriptController.h
@@ -104,6 +104,7 @@
WTF::TextPosition eventHandlerPosition() const;
+ void enableEval();
void disableEval();
static bool processingUserGesture();
diff --git a/Source/WebCore/bindings/v8/ScriptController.cpp b/Source/WebCore/bindings/v8/ScriptController.cpp
index 42cda7a..c962e03 100644
--- a/Source/WebCore/bindings/v8/ScriptController.cpp
+++ b/Source/WebCore/bindings/v8/ScriptController.cpp
@@ -279,13 +279,25 @@
return m_proxy->windowShell()->isContextInitialized();
}
+void ScriptController::enableEval()
+{
+ // We don't call initContextIfNeeded because contexts have eval enabled by default.
+
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> v8Context = proxy()->windowShell()->context();
+ if (v8Context.IsEmpty())
+ return;
+
+ v8Context->AllowCodeGenerationFromStrings(true);
+}
+
void ScriptController::disableEval()
{
- if (!m_proxy->windowShell()->initContextIfNeeded())
+ if (!proxy()->windowShell()->initContextIfNeeded())
return;
v8::HandleScope handleScope;
- v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame);
+ v8::Handle<v8::Context> v8Context = proxy()->windowShell()->context();
if (v8Context.IsEmpty())
return;
diff --git a/Source/WebCore/bindings/v8/ScriptController.h b/Source/WebCore/bindings/v8/ScriptController.h
index c71d284..41d71ce 100644
--- a/Source/WebCore/bindings/v8/ScriptController.h
+++ b/Source/WebCore/bindings/v8/ScriptController.h
@@ -126,6 +126,7 @@
// Check if the javascript engine has been initialized.
bool haveInterpreter() const;
+ void enableEval();
void disableEval();
static bool canAccessFromCurrentOrigin(Frame*);
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 2e50352..e46f9e1 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -540,6 +540,8 @@
if (clearScriptObjects)
m_frame->script()->clearScriptObjects();
+ m_frame->script()->enableEval();
+
m_frame->navigationScheduler()->clear();
m_checkTimer.stop();