Changeset 128670 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Sep 14, 2012, 4:33:20 PM (13 years ago)
Author:
[email protected]
Message:

JSC should throw a more descriptive exception when blocking 'eval' via CSP.
https://bugs.webkit.org/show_bug.cgi?id=94331

Patch by Mike West <[email protected]> on 2012-09-14
Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Unless explicitly whitelisted, the 'script-src' Content Security Policy
directive blocks 'eval' and 'eval'-like constructs such as
'new Function()'. When 'eval' is encountered in code, an 'EvalError' is
thrown, but the associated message is poor: "Eval is disabled" doesn't
give developers enough information about why their code isn't behaving
as expected.

This patch adds an 'errorMessage' parameter to the JavaScriptCore method
used to disable 'eval'; ContentSecurityPolicy has the opportunity to
pass in a more detailed and descriptive error that contains more context
for the developer.

  • runtime/Executable.cpp:

(JSC::EvalExecutable::compileInternal):

Drop the hard-coded "Eval is disabled" error message in favor of
reading the error message off the global object.

  • runtime/FunctionConstructor.cpp:

(JSC::FunctionConstructor::getCallData):

Drop the hard-coded "Function constructor is disabled" error message
in favor of reading the error message off the global object.

  • runtime/JSGlobalObject.h:

(JSGlobalObject):
(JSC::JSGlobalObject::evalEnabled):

Making this accessor method const.

(JSC::JSGlobalObject::evalDisabledErrorMessage):

Accessor for the error message set via 'setEvalDisabled'.

(JSC::JSGlobalObject::setEvalEnabled):

Adding an 'errorMessage' parameter which is stored on the global
object, and used when exceptions are thrown.

Source/WebCore:

Unless explicitly whitelisted, the 'script-src' Content Security Policy
directive blocks 'eval' and 'eval'-like constructs such as
'new Function()'. When 'eval' is encountered in code, an 'EvalError' is
thrown, but the associated message is poor: "Eval is disabled" doesn't
give developers enough information about why their code isn't behaving
as expected.

This patch adds an 'errorMessage' parameter to the JavaScriptCore method
used to disable 'eval'; ContentSecurityPolicy has the opportunity to
pass in a more detailed and descriptive error that contains more context
for the developer.

The new error message is tested by adjusting existing tests; nothing new
is required.

  • bindings/js/ScriptController.cpp:

(WebCore::ScriptController::initScript):

Read the error message off the document's ContentSecurityPolicy.

(WebCore::ScriptController::disableEval):

  • bindings/js/ScriptController.h:

(ScriptController):

Pipe the error message through to JSGlobalObject when disabling eval

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::disableEval):

  • bindings/js/WorkerScriptController.h:

(WorkerScriptController):

Pipe the error message through to JSGlobalObject when disabling eval

  • bindings/v8/ScriptController.cpp:

(WebCore::ScriptController::disableEval):

  • bindings/v8/ScriptController.h:

(ScriptController):

  • bindings/v8/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::disableEval):

  • bindings/v8/WorkerScriptController.h:

(WorkerScriptController):

Placeholder for V8 piping to be built in webk.it/94332.

  • dom/Document.cpp:

(WebCore::Document::disableEval):

  • dom/Document.h:

(Document):

  • dom/ScriptExecutionContext.h:

(ScriptExecutionContext):

Pipe the error message through to the ScriptController when
disabling eval.

  • page/ContentSecurityPolicy.cpp:

(WebCore::CSPDirectiveList::evalDisabledErrorMessage):

Accessor for the error message that ought be displayed to developers
when 'eval' used while disabled for a specific directive list.

(WebCore::CSPDirectiveList::setEvalDisabledErrorMessage):

Mutator for the error message that ought be displayed to developers
when 'eval' used while disabled for a specific directive list.

(CSPDirectiveList):
(WebCore::CSPDirectiveList::create):

Upon creation of a CSPDirectiveList, set the error message if the
directive list disables 'eval'.

(WebCore::ContentSecurityPolicy::didReceiveHeader):

Pass the error message into ScriptExecutionContext::disableEval.

(WebCore::ContentSecurityPolicy::evalDisabledErrorMessage):

Public accessor for the policy's error message; walks the list of
directive lists and returns the first error message found.

(WebCore):

  • page/ContentSecurityPolicy.h:
  • workers/WorkerContext.cpp:

(WebCore::WorkerContext::disableEval):

  • workers/WorkerContext.h:

(WorkerContext):

Pipe the error message through to the ScriptController when
disabling eval.

LayoutTests:

  • http/tests/security/contentSecurityPolicy/eval-blocked-expected.txt:
  • http/tests/security/contentSecurityPolicy/eval-blocked-in-about-blank-iframe-expected.txt:
  • http/tests/security/contentSecurityPolicy/function-constructor-blocked-expected.txt:
Location:
trunk/Source/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r128667 r128670  
     12012-09-14  Mike West  <[email protected]>
     2
     3        JSC should throw a more descriptive exception when blocking 'eval' via CSP.
     4        https://bugs.webkit.org/show_bug.cgi?id=94331
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Unless explicitly whitelisted, the 'script-src' Content Security Policy
     9        directive blocks 'eval' and 'eval'-like constructs such as
     10        'new Function()'. When 'eval' is encountered in code, an 'EvalError' is
     11        thrown, but the associated message is poor: "Eval is disabled" doesn't
     12        give developers enough information about why their code isn't behaving
     13        as expected.
     14
     15        This patch adds an 'errorMessage' parameter to the JavaScriptCore method
     16        used to disable 'eval'; ContentSecurityPolicy has the opportunity to
     17        pass in a more detailed and descriptive error that contains more context
     18        for the developer.
     19
     20        * runtime/Executable.cpp:
     21        (JSC::EvalExecutable::compileInternal):
     22            Drop the hard-coded "Eval is disabled" error message in favor of
     23            reading the error message off the global object.
     24        * runtime/FunctionConstructor.cpp:
     25        (JSC::FunctionConstructor::getCallData):
     26            Drop the hard-coded "Function constructor is disabled" error message
     27            in favor of reading the error message off the global object.
     28        * runtime/JSGlobalObject.h:
     29        (JSGlobalObject):
     30        (JSC::JSGlobalObject::evalEnabled):
     31            Making this accessor method const.
     32        (JSC::JSGlobalObject::evalDisabledErrorMessage):
     33            Accessor for the error message set via 'setEvalDisabled'.
     34        (JSC::JSGlobalObject::setEvalEnabled):
     35            Adding an 'errorMessage' parameter which is stored on the global
     36            object, and used when exceptions are thrown.
     37
    1382012-09-14  Filip Pizlo  <[email protected]>
    239
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r127958 r128670  
    203203    } else {
    204204        if (!lexicalGlobalObject->evalEnabled())
    205             return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled")));
     205            return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage()));
    206206        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
    207207        if (!evalNode) {
  • trunk/Source/JavaScriptCore/runtime/FunctionConstructor.cpp

    r127505 r128670  
    8383{
    8484    if (!globalObject->evalEnabled())
    85         return throwError(exec, createEvalError(exec, ASCIILiteral("Function constructor is disabled")));
     85        return throwError(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
    8686    return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position);
    8787}
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r127363 r128670  
    156156
    157157        bool m_evalEnabled;
     158        String m_evalDisabledErrorMessage;
    158159        bool m_experimentsEnabled;
    159160
     
    305306        bool isDynamicScope(bool& requiresDynamicChecks) const;
    306307
    307         void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; }
    308         bool evalEnabled() { return m_evalEnabled; }
     308        bool evalEnabled() const { return m_evalEnabled; }
     309        const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
     310        void setEvalEnabled(bool enabled, const String& errorMessage = String())
     311        {
     312            m_evalEnabled = enabled;
     313            m_evalDisabledErrorMessage = errorMessage;
     314        }
    309315
    310316        void resetPrototype(JSGlobalData&, JSValue prototype);
Note: See TracChangeset for help on using the changeset viewer.