Issue 654280:
Security: Use of unvalidated URL in PDF viewer

Issue description

Chrome version: Stable (53.0.2785.116) and latest (56.0.2886.0)
When a PDF is opened in Chrome, the PDFium plugin is used as follows:
(1) <embed> by webpage -> Chrome loads PDF plugin
(2) PDF plugin loads <iframe> with PDF helper extension.
(3) PDF helper extension loads <embed> with privileged plugin.
(4) Privileged plugin trusts any messages from the host.
A limited API is available between (1) and (2); for same-origin PDFs, this includes reading the content of the PDF.
The plugin at (4) cannot be loaded by a web page (after bug 520422 ).
Now I found that (3) is web-accessible [1] *and* trusts the query string to contain the real URL (originUrl_). This URL is used for multiple security decisions, including but not limited to:
- The originUrl_ can be set to a PDF that redirects elsewhere, and because the helper extension thinks that it's dealing with a same-origin PDF, it will happily leak cross-origin data.
- The API for chrome://print pages is more extensive, it can be used to load any PDF, and be used to open e.g. file:-URLs in a new tab.
I have attached a PoC for the above two examples.
1. Start server.py (this is for the second example).
2. If using Chrome 53, start with --isolate-extensions to force Site isolation for extensions (this is on a field trial in 53, and enabled by default in Chrome 54). This is needed to allow the chrome:// resources in the helper extension to load (otherwise the frame will run in the unprivileged tab process).
3. Open http://localhost:8100
4. Click on the second button, and see the content of a PDF at another origin being printed in the page.
5. Click on the first button, and see file:///etc/passwd (or C:\ on Windows) being opened in a new tab (this example does not work in Chrome 54+ any more because the helper extension can no longer embed the chrome://print plugin).
TL;DR Use of unvalidated URL, leading to multiple issues including a same origin bypass. Site isolation made the vulnerability exploitable.
[1] https://chromium.googlesource.com/chromium/src/+/bbf2420306f6d0a3c85d10a4115ab254b3912162/chrome/browser/resources/pdf/manifest.json#21
[2] https://chromium.googlesource.com/chromium/src/+/383ff955ecb5eddb6a91eae873f617f814426cc4/chrome/browser/resources/pdf/browser_api.js#182

The PoC includes some browser version detection, and switches to a different method in Chrome 54. The post-53 code path is equivalent to opening data:application/pdf, in a new tab. Maybe whatever that necessitated the logic for 54+ is also needed in 53.0.2785.143. Try opening this tab and retry the PoC.
And when starting with --isolate-extensions, make sure that all Chrome processes were shut down before you started chrome. Otherwise the flag will not apply.
I tried the PoC with 53, 54, 55 and 56 before reporting.
Do note that the PoC that opens a file:-URL does not work in 54+ (maybe also not in 53.0.2785.143?). I haven't investigated why because the other example (reading data cross-origin) is much more severe and already shows why this should be fixed.

Thanks for the report!
Just to clarify, --isolate-extensions is not enabled at all in M53. It's enabled via Finch trial in M54 and enabled by default in M55.
That said, we should definitely get this fixed.

The exploit from the initial report relied on site isolation to work, but the vulnerability can also be exploited without site isolation:
1. Download server.py from the initial report plus the attached index.html in the same folder.
2. Start the server: python server.py
3. Visit http://localhost:8100
4. Click on the button.
Result in 54.0.2840.59 (without patch): A cross-origin PDF is briefly loaded, its content is selected and shown by index.html.
Expected (in M55/M56, M54 with patch): the PDF is not opened.
Requesting a merge of my patch to break the exploit in M54.

If this bug allows reading of files cross-origin, then this is likely in the same realm as "A bypass of the same origin policy for pages that meet several preconditions", which is medium severity bug. Since the fix isn't complex, I think we should take it for M54, though that would require writing a postmortem.