bug 515442 CSP inline script protection

This commit is contained in:
Daniel Veditz 2010-02-23 13:20:46 -08:00
parent 5d0c007c48
commit ac0251d255
4 changed files with 80 additions and 3 deletions

View File

@ -70,6 +70,13 @@
#include "nsThreadUtils.h"
#include "nsIChannelClassifier.h"
#include "nsDocShellCID.h"
#include "nsIContentSecurityPolicy.h"
#include "prlog.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gCspPRLog;
#endif
//////////////////////////////////////////////////////////////
// Per-request data structure
@ -129,6 +136,11 @@ nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
mDeferEnabled(PR_FALSE),
mUnblockOnloadWhenDoneProcessing(PR_FALSE)
{
// enable logging for CSP
#ifdef PR_LOGGING
if (!gCspPRLog)
gCspPRLog = PR_NewLogModule("CSP");
#endif
}
nsScriptLoader::~nsScriptLoader()
@ -563,6 +575,24 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return rv;
}
} else {
// in-line script
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i ****with CSP****"));
PRBool inlineOK;
// this call will send violation reports when necessary
rv = NS_SUCCEEDED(csp->GetAllowsInlineScript(&inlineOK));
NS_ENSURE_SUCCESS(rv, rv);
if (!inlineOK) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts (2)"));
return NS_ERROR_FAILURE;
}
}
request->mDefer = PR_FALSE;
request->mLoading = PR_FALSE;
request->mIsInline = PR_TRUE;

View File

@ -341,6 +341,9 @@ _TEST_FILES = test_bug5141.html \
file_CSP_frameancestors.sjs \
file_CSP_frameancestors_main.html \
file_CSP_frameancestors_main.js \
test_CSP_inlinescript.html \
file_CSP_inlinescript_main.html \
file_CSP_inlinescript_main.html^headers^ \
test_bug540854.html \
bug540854.sjs \
$(NULL)

View File

@ -94,6 +94,7 @@
#include "nsCOMArray.h"
#include "nsEventListenerService.h"
#include "nsDOMEvent.h"
#include "nsIContentSecurityPolicy.h"
#define EVENT_TYPE_EQUALS( ls, type, userType ) \
(ls->mEventType && ls->mEventType == type && \
@ -663,6 +664,8 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
return NS_ERROR_FAILURE;
}
nsresult rv;
nsCOMPtr<nsINode> node(do_QueryInterface(aObject));
nsCOMPtr<nsIDocument> doc;
@ -697,7 +700,31 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
// loaded as data.
return NS_OK;
}
// return early preventing the event listener from being added
// 'doc' is fetched above
if (doc) {
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
PRBool inlineOK;
// this call will trigger violaton reports if necessary
rv = csp->GetAllowsInlineScript(&inlineOK);
NS_ENSURE_SUCCESS(rv, rv);
if ( !inlineOK ) {
//can log something here too.
//nsAutoString attr;
//aName->ToString(attr);
//printf(" *** CSP bailing on adding event listener for: %s\n",
// ToNewCString(attr));
return NS_OK;
}
}
}
// This might be the first reference to this language in the global
// We must init the language before we attempt to fetch its context.
if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
@ -709,7 +736,6 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
void *scope = global->GetScriptGlobal(aLanguage);
nsresult rv;
if (!aDeferCompilation) {
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =

View File

@ -78,6 +78,7 @@
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIWritablePropertyBag2.h"
#include "nsIContentSecurityPolicy.h"
static NS_DEFINE_CID(kJSURICID, NS_JSURI_CID);
@ -190,6 +191,24 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
return NS_ERROR_DOM_RETVAL_UNDEFINED;
}
nsresult rv;
// CSP check: javascript: URIs disabled unless "inline" scripts are
// allowed.
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if(csp) {
PRBool allowsInline;
// this call will send violation reports as warranted (and return true if
// reportOnly is set).
rv = csp->GetAllowsInlineScript(&allowsInline);
NS_ENSURE_SUCCESS(rv, rv);
// TODO: log that we're blocking this javascript: uri
if (!allowsInline)
return NS_ERROR_DOM_RETVAL_UNDEFINED;
}
// Get the global object we should be running on.
nsIScriptGlobalObject* global = GetGlobalObject(aChannel);
@ -213,7 +232,6 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
JSObject *globalJSObject = innerGlobal->GetGlobalJSObject();
nsresult rv;
nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(global, &rv));
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;