Closed Bug 970790 Opened 10 years ago Closed 9 years ago

CSP reports are not shown in Web Console for actions taken from the web console or developer toolbar, and in various other cases

Categories

(DevTools :: Console, defect, P3)

28 Branch
defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: igor, Assigned: ckerschb)

References

Details

It looks like CSP violation reports are no longer shown in the web console, a possible regression from the bug 770099.

To reproduce, go to www.dnb.no, open web console (Ctrl-Shift-K) and type there:

document.body.appendChild(document.createElement('script')).src = 'https://www.yahoo.com/';

Note that www.yahoo.com is not loaded and the error console shows CSP violation report. However, the web console shows no traces of that. There is no mentioning of CSP report in the console and the net tab does not show the CSP report HTTP request. 

Setting security.csp.debug to true in about:config has not affected this.
Thank you Igor for the bug report.

Mark: did any CSP-related changes land that could cause this bug?
Flags: needinfo?(mgoodwin)
(In reply to Mihai Sucan [:msucan] from comment #1)
> Mark: did any CSP-related changes land that could cause this bug?

I don't know. There's a good chance that Garrett will know (given that he's working on CSP and has done much work on the security messages in the web console). Garrett, any clues?
Flags: needinfo?(mgoodwin) → needinfo?(grobinson)
I see the expected message in the web console in 26, so this is definitely a regression. This is likely caused by the changes from either bug 607067 or bug 909241, which did a significant rework of the CSP violation reporting. I'll take a closer look.
Assignee: nobody → grobinson
Flags: needinfo?(grobinson)
Sorry for letting this one sit for a bit. I created a test environment and can confirm that I am getting CSP errors in the Web Console, as expected (there are tests for this as well).

So the problem here is actually specific to the given test case, in which the page is modified using the Web Console. I was able to reproduce the issue described in Comment 1 in my test case, where:

1. The test document has a CSP of "script-src 'self'"
2. The document has <script src="https://www.yahoo.com/"></script>, which is blocked by CSP, and a corresponding error message is logged to the Web Console (and Browser Console).
3. I open the Web Console and paste the JS from Comment 1. This results in the behavior described in Comment 1: the script tag is injected and blocked by CSP, but the error only appears in the Browser Console and not in the Web Console.

This is almost certainly due to confusion over which window is active (innerWindowID) when the script is injected via the Web Console.

msucan, do you have any ideas about this?
Flags: needinfo?(mihai.sucan)
igor, the test case from Comment 1 is broken (www.db.no does not resolve). Do you think you could fix it? This makes it easier for others to help.
Flags: needinfo?(igor)
(In reply to Garrett Robinson [:grobinson] from comment #5)
> igor, the test case from Comment 1 is broken (www.db.no does not resolve).
> Do you think you could fix it? This makes it easier for others to help.

It was written in the comment 0 : go to www.dnb.no (not www.db.no)
Flags: needinfo?(mihai.sucan)
Flags: needinfo?(igor)
Garret, yes, that seems to be the case. There's confusion about the window ID.
So Igor - this is only a problem when you attempt to trigger CSP by injecting script via the Web Console. Actual injected content on pages will trigger CSP reports, and they will be printed in the Web Console as expected. I will try to fix this issue, but it is not a priority.
(In reply to Garrett Robinson [:grobinson] from comment #8)
> So Igor - this is only a problem when you attempt to trigger CSP by
> injecting script via the Web Console.

It looks you are right. If on www.dnb.no I type in the console:

setTimeout(function() {document.body.appendChild(document.createElement('script')).src = 'https://www.yahoo.com/';}, 10*1000)

and within 10 seconds give focus the web page by clicking on it, then yes, the report is shown. But if after hitting the enter in the web console to submit the above fragment I do nothing and just wait, then the report is not shown.
Nice observation! That should help us narrow it down. The bug is somewhere in `innerWindowFromRequest` in CSPUtils.jsm.
Maybe the wrong window has focus (web console instead of document window)?  This could be causing a problem by fetching the wrong window given the focus:

http://mxr.mozilla.org/mozilla-central/source/content/base/src/CSPUtils.jsm#1954
1954   if (win) {
1955     try {
1956        let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
1957        return winUtils.currentInnerWindowID;
1958     } catch (ex) {
1959       return null;
1960     }
1961   }

I wonder if there's a way to check which window gets returned here to see if we are indeed getting a window corresponding to the console and not the web content...
That code seems fine. It fetches the network request's associatedWindow ID. Shouldn't be affected by focus.
Blocks: 984808
Priority: -- → P3
Assignee: garrett.f.robinson+mozilla → mozilla
Summary: CSP reports are not shown in Web Console → CSP reports are not shown in Web Console for actions taken from the web console or developer toolbar
This is actually very very broken.

What happens is that nsDocument::InitCSP creates an nsCSPContext and calls SetRequestContext() on it.  SetRequestContext does:

  mInnerWindowID = nsContentUtils::GetInnerWindowID(aChannel);

which will go and dig up the current inner window of the load context of the channel.

Sadly, this has absolutely nothing to do with the document whose CSP we're initializing.  In fact, the inner window of that document hasn't even been created yet at that point, much less set as the current inner.

Specifically, the InitCSP() call happens with this stack:

#1  0x0000000102f409d6 in nsDocument::InitCSP (this=0x131fd7000, aChannel=0x1315ca850) at nsDocument.cpp:3046
#2  0x0000000102f3ed8c in nsDocument::StartDocumentLoad (this=0x131fd7000, aCommand=0x1079f6800 "view", aChannel=0x1315ca850, aLoadGroup=0x1290a5400, aContainer=0x1290c31a0, aDocListener=0x1495a37c8, aReset=true, aSink=0x0) at nsDocument.cpp:2752
#3  0x00000001042e3840 in nsHTMLDocument::StartDocumentLoad (this=0x131fd7000, aCommand=0x1079f6800 "view", aChannel=0x1315ca850, aLoadGroup=0x1290a5400, aContainer=0x1290c31a0, aDocListener=0x1495a37c8, aReset=true, aSink=0x0) at nsHTMLDocument.cpp:594
#4  0x00000001055451f9 in nsContentDLF::CreateDocument (this=0x11c1ba120, aCommand=0x1079f6800 "view", aChannel=0x1315ca850, aLoadGroup=0x1290a5400, aContainer=0x1290c31a0, aDocumentCID=@0x107e804f8, aDocListener=0x1495a37c8, aContentViewer=0x7fff5fbfba00) at nsContentDLF.cpp:402
#5  0x0000000105544a14 in nsContentDLF::CreateInstance (this=0x11c1ba120, aCommand=0x1079f6800 "view", aChannel=0x1315ca850, aLoadGroup=0x1290a5400, aContentType=@0x1495a37e0, aContainer=0x1290c31a0, aExtraInfo=0x0, aDocListener=0x1495a37c8, aDocViewer=0x7fff5fbfba00) at nsContentDLF.cpp:201
#6  0x0000000105864a79 in nsDocShell::NewContentViewerObj (this=0x1290c3000, aContentType=@0x1495a37e0, aRequest=0x1315ca850, aLoadGroup=0x1290a5400, aContentHandler=0x1495a37c8, aViewer=0x7fff5fbfba00) at nsDocShell.cpp:9120
#7  0x0000000105828b11 in nsDocShell::CreateContentViewer (this=0x1290c3000, aContentType=@0x1495a37e0, aRequest=0x1315ca850, aContentHandler=0x1495a37c8) at nsDocShell.cpp:8922

and the inner window is not created until this stack:

#0  nsGlobalWindow::nsGlobalWindow (this=0x1306de000, aOuterWindow=0x127d23800) at ../../../mozilla/dom/base/nsGlobalWindow.cpp:1226
#1  0x0000000102d5c90b in nsGlobalWindow::Create (aOuterWindow=0x127d23800) at ../../../mozilla/dom/base/nsGlobalWindow.cpp:13858
#2  0x0000000102d5a97c in nsGlobalWindow::SetNewDocument (this=0x127d23800, aDocument=0x131fd7000, aState=0x0, aForceReuseInnerWindow=false) at ../../../mozilla/dom/base/nsGlobalWindow.cpp:2495
#3  0x0000000102d5df56 in non-virtual thunk to nsGlobalWindow::SetNewDocument(nsIDocument*, nsISupports*, bool) (this=0x127d23820, aDocument=0x131fd7000, aState=0x0, aForceReuseInnerWindow=false) at ../../../mozilla/dom/base/nsGlobalWindow.cpp:2728
#4  0x000000010518a67d in nsDocumentViewer::InitInternal (this=0x13116e370, aParentWidget=0x0, aState=0x0, aBounds=@0x7fff5fbfb438, aDoCreation=true, aNeedMakeCX=true, aForceSetNewDocument=true) at nsDocumentViewer.cpp:885
#5  0x0000000105189b84 in nsDocumentViewer::Init (this=0x13116e370, aParentWidget=0x0, aBounds=@0x7fff5fbfb438) at nsDocumentViewer.cpp:625
#6  0x0000000105859af4 in nsDocShell::SetupNewViewer (this=0x1290c3000, aNewViewer=0x13116e370) at nsDocShell.cpp:9257
#7  0x00000001058588eb in nsDocShell::Embed (this=0x1290c3000, aContentViewer=0x13116e370, aCommand=0x107b6bee8 "", aExtraInfo=0x0) at nsDocShell.cpp:7164
#8  0x0000000105829635 in nsDocShell::CreateContentViewer (this=0x1290c3000, aContentType=@0x1495a37e0, aRequest=0x1315ca850, aContentHandler=0x1495a37c8) at nsDocShell.cpp:9065

In any case, it's possible that this will find an inner window id that just happens to be in the same tab (as opposed to being chrome, say!) and things will show up in the console.  Sometimes.  And sometimes not.

This seems like it would be a problem for violation reports in general, not just for ones for actions taken from the web console or dev toolbar....  Basically, whether the web developer sees the violation report in the web console is totally random and depends on exactly how the page was loaded (!).
Flags: needinfo?(mozilla)
Summary: CSP reports are not shown in Web Console for actions taken from the web console or developer toolbar → CSP reports are not shown in Web Console for actions taken from the web console or developer toolbar, and in various other cases
Thanks Boris for pointing that out. In fact, we could easily store the channel (or alternatively the loadInfo object) within ::SetRequestContext() [1] and query the innerWindowId in ::SendReports() [2]; which is not only where we send reports but also where we log errors to the console.

However, we would still face the same problem within the CSP parser, because right after ::SetRequestContext() we call ::AppendPolicy() [3] and hand off mInnerWindowID to the parser so the parser can log to the web console. At that time though, we still have the same problem as explained by Boris where we most likely don't have an innerwindow yet.

At the moment I can't think of any alternative solutions here. Sid, Boris, any ideas?

[1] http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCSPContext.cpp#592
[2] http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCSPContext.cpp#764
[3] http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCSPContext.cpp#359
Flags: needinfo?(sstamm)
Flags: needinfo?(mozilla)
Seems to me the best way forward is to queue up violation reports we want to send to the console, then when the right inner window is available, stuff it into the nsIContentSecurityPolicy instance and start emptying the queue.
Flags: needinfo?(sstamm)
Blocks: 1181379
OS: Windows 7 → All
Hardware: x86 → All
Hopefully the queue for console messages implemented for Bug 1188028 also fixes the issue in this bug. We should check once Bug 1188028 has landed.
Status: NEW → ASSIGNED
Depends on: 1188028
(In reply to Christoph Kerschbaumer [:ckerschb] from comment #18)
> Hopefully the queue for console messages implemented for Bug 1188028 also
> fixes the issue in this bug. We should check once Bug 1188028 has landed.

Just verified that using the console message queue for CSP implemented within bug 1188028 fixed the problem here.
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Blocks: 1389874
Product: Firefox → DevTools
You need to log in before you can comment on or make changes to this bug.