Bug 1100630 - Print Related JS-Line on CSP Violation (if any) r=ckerschb,dveditz

Differential Revision: https://phabricator.services.mozilla.com/D31420

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sebastian Streich 2019-07-17 10:54:07 +00:00
Родитель 6ce65b9679
Коммит 975121a09a
13 изменённых файлов: 228 добавлений и 20 удалений

Просмотреть файл

@ -23,6 +23,16 @@ support-files =
test-cd-iframe-parent.html
test-console-api-iframe.html
test-csp-violation.html
test-csp-violation-inline.html
test-csp-violation-inline.html^headers^
test-csp-violation-base-uri.html
test-csp-violation-base-uri.html^headers^
test-csp-violation-form-action.html
test-csp-violation-form-action.html^headers^
test-csp-violation-frame-ancestor-child.html^headers^
test-csp-violation-frame-ancestor-child.html
test-csp-violation-frame-ancestor-parent.html^headers^
test-csp-violation-frame-ancestor-parent.html
test-cspro.html
test-cspro.html^headers^
test-iframe-child.html

Просмотреть файл

@ -8,22 +8,105 @@
"use strict";
const TEST_URI = "data:text/html;charset=utf8,Web Console CSP violation test";
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation.html";
const CSP_VIOLATION_MSG =
"Content Security Policy: The page\u2019s settings " +
"blocked the loading of a resource at " +
"http://some.example.com/test.png (\u201cimg-src\u201d).";
add_task(async function() {
const TEST_URI = "data:text/html;charset=utf8,Web Console CSP violation test";
const hud = await openNewTabAndConsole(TEST_URI);
hud.ui.clearOutput();
{
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation.html";
const CSP_VIOLATION_MSG =
"Content Security Policy: The page\u2019s settings " +
"blocked the loading of a resource at " +
"http://some.example.com/test.png (\u201cimg-src\u201d).";
const onRepeatedMessage = waitForRepeatedMessage(hud, CSP_VIOLATION_MSG, 2);
await loadDocument(TEST_VIOLATION);
await onRepeatedMessage;
ok(true, "Received expected messages");
}
hud.ui.clearOutput();
// Testing CSP Inline Violations
{
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation-inline.html";
const CSP_VIOLATION =
`Content Security Policy: The pages settings blocked` +
` the loading of a resource at inline (“style-src”).`;
const VIOLATION_LOCATION_HTML = "test-csp-violation-inline.html:18:1";
const VIOLATION_LOCATION_JS = "test-csp-violation-inline.html:14:24";
await loadDocument(TEST_VIOLATION);
// Triggering the Violation via HTML
let msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
let locationNode = msg.querySelector(".message-location");
info(`EXPECT ${VIOLATION_LOCATION_HTML} GOT: ${locationNode.textContent}`);
ok(
locationNode.textContent == VIOLATION_LOCATION_HTML,
"Printed the CSP Violation with HTML Context"
);
// Triggering the Violation via JS
hud.ui.clearOutput();
hud.jsterm.execute("window.violate()");
msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
locationNode = msg.querySelector(".message-location");
info(`EXPECT ${VIOLATION_LOCATION_JS} GOT: ${locationNode.textContent}`);
ok(
locationNode.textContent == VIOLATION_LOCATION_JS,
"Printed the CSP Violation with JS Context"
);
}
hud.ui.clearOutput();
// Testing Base URI
{
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation-base-uri.html";
const CSP_VIOLATION = `Content Security Policy: The pages settings blocked the loading of a resource at https://evil.com/ (“base-uri”).`;
const VIOLATION_LOCATION = "test-csp-violation-base-uri.html:15:24";
await loadDocument(TEST_VIOLATION);
let msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
ok(msg, "Base-URI validation was Printed");
// Triggering the Violation via JS
hud.ui.clearOutput();
hud.jsterm.execute("window.violate()");
msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
const locationNode = msg.querySelector(".message-location");
console.log(locationNode.textContent);
ok(
locationNode.textContent == VIOLATION_LOCATION,
"Base-URI validation was Printed with the Responsible JS Line"
);
}
hud.ui.clearOutput();
// Testing CSP Form Action
{
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation-form-action.html";
const CSP_VIOLATION = `Content Security Policy: The pages settings blocked the loading of a resource at https://evil.com/evil.com (“form-action”).`;
const VIOLATION_LOCATION = "test-csp-violation-form-action.html:14:39";
const onRepeatedMessage = waitForRepeatedMessage(hud, CSP_VIOLATION_MSG, 2);
await loadDocument(TEST_VIOLATION);
await onRepeatedMessage;
ok(true, "Received expected messages");
await loadDocument(TEST_VIOLATION);
const msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
const locationNode = msg.querySelector(".message-location");
info(`EXPECT ${VIOLATION_LOCATION} GOT: ${locationNode.textContent}`);
ok(
locationNode.textContent == VIOLATION_LOCATION,
"JS Line which Triggered the CSP-Form Action Violation was Printed"
);
}
hud.ui.clearOutput();
// Testing CSP Frame Ancestors Directive
{
const TEST_VIOLATION =
"https://example.com/browser/devtools/client/webconsole/" +
"test/mochitest/test-csp-violation-frame-ancestor-parent.html";
const CSP_VIOLATION =
`Content Security Policy: The pages settings blocked` +
` the loading of a resource at ${TEST_VIOLATION} (“frame-ancestors”).`;
await loadDocument(TEST_VIOLATION);
const msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
ok(msg, "Frame-Ancestors violation by html was printed");
}
});

Просмотреть файл

@ -0,0 +1,18 @@
<html>
<head>
<title>CSP Base-URI Violation Test </title>
<base href="https://evil.com/">
</head>
<body>
<h1> Crashing the Base Element</h1>
</body>
<script>
"use strict";
window.violate = ()=>{
document.head.innerHTML = "";
const b = document.createElement("base");
b.href = "https://evil.com";
document.head.append(b);
};
</script>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: base-uri 'self';

Просмотреть файл

@ -0,0 +1,16 @@
<html>
<head>
<title>CSP Base-URI Violation Test </title>
<base href="https://evil.com/">
</head>
<body>
<form action="evil.com" >
<input type="text" value="test" name="test" />
<button type="submit">Submit Button</button>
</form>
</body>
<script>
"use strict";
document.querySelector("form").submit();
</script>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: form-action 'self';

Просмотреть файл

@ -0,0 +1,9 @@
<html>
<head>
<title>CSP frame-ancestors Violation Test </title>
<base href="https://evil.com/">
</head>
<body>
<h1> This Should not be Loadable</h1>
</body>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: frame-ancestors 'none';

Просмотреть файл

@ -0,0 +1,21 @@
<html>
<head>
<title>CSP frame-ancestors Violation Test </title>
<base href="https://evil.com/">
</head>
<body>
<iframe src="https://example.com/browser/devtools/client/webconsole/test/mochitest/test-csp-violation-frame-ancestor-child.html">
</iframe>
</body>
<script>
"use strict";
window.violate = ()=>{
const iframe = document.querySelector("iframe");
const src = iframe.src;
iframe.src = "";
requestAnimationFrame(() => {
iframe.src = src;
});
};
</script>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: form-action 'self';

Просмотреть файл

@ -0,0 +1,21 @@
<html>
<head>
<title>CSP Inline Violations Test</title>
</head>
<body>
This Background should be neither Red nor Blue c:
</body>
<script>
"use strict";
window.violate = () =>{
const style = document.createElement("style");
style.innerHTML = "body { background-color: red; }";
document.head.appendChild(style);
};
</script>
<style>
background-color:blue;
</style>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: style-src 'self';

Просмотреть файл

@ -53,6 +53,7 @@
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/Element.h"
#include "nsXULAppAPI.h"
#include "nsJSUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -211,6 +212,15 @@ bool nsCSPContext::permitsInternal(
// decision may be wrong due to the inability to get the nonce, and will
// incorrectly fail the unit tests.
if (!aIsPreload && aSendViolationReports) {
uint32_t lineNumber = 0;
uint32_t columnNumber = 0;
nsAutoCString spec;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
nsJSUtils::GetCallingLocation(cx, spec, &lineNumber, &columnNumber);
// If GetCallingLocation fails linenumber & columnNumber are set to 0
// anyway so we can skip checking if that is the case.
}
AsyncReportViolation(
aTriggeringElement, aCSPEventListener,
(aSendContentLocationInViolationReports ? aContentLocation
@ -220,10 +230,10 @@ bool nsCSPContext::permitsInternal(
null */
violatedDirective, p, /* policy index */
EmptyString(), /* no observer subject */
EmptyString(), /* no source file */
EmptyString(), /* no script sample */
0, /* no line number */
0); /* no column number */
NS_ConvertUTF8toUTF16(spec), /* source file */
EmptyString(), /* no script sample */
lineNumber, /* line number */
columnNumber); /* column number */
}
}
}
@ -487,6 +497,21 @@ void nsCSPContext::reportInlineViolation(
mSelfURI->GetSpec(sourceFile);
}
uint32_t lineNumber = aLineNumber;
uint32_t columnNumber = aColumnNumber;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
if (!nsJSUtils::GetCallingLocation(cx, sourceFile, &lineNumber,
&columnNumber)) {
// Get Calling Location resets line/col to 0
// so we reset those to the intial arguments
// in case it failed
lineNumber = aLineNumber;
columnNumber = aColumnNumber;
}
}
AsyncReportViolation(aTriggeringElement, aCSPEventListener,
nullptr, // aBlockedURI
BlockedContentSource::eInline, // aBlockedSource
@ -496,8 +521,8 @@ void nsCSPContext::reportInlineViolation(
observerSubject, // aObserverSubject
NS_ConvertUTF8toUTF16(sourceFile), // aSourceFile
aContent, // aScriptSample
aLineNumber, // aLineNum
aColumnNumber); // aColumnNum
lineNumber, // aLineNum
columnNumber); // aColumnNum
}
NS_IMETHODIMP