Ngx-extended-pdf-viewer: Chrome Content Security Policy (CSP) failures when using "Blob" sources

Created on 3 Nov 2020  路  14Comments  路  Source: stephanrauh/ngx-extended-pdf-viewer

Describe the bug
When using a "Blob" type as [src] input of ngx-extended-pdf-viewer, the viewer fails on Chrome due to a Content Security Policy (CSP) denial.

At first sight, the issue comes from the URL.createObjectURL API used here (an internal redirection happens) :
https://github.com/stephanrauh/ngx-extended-pdf-viewer/blob/91b45e1/projects/ngx-extended-pdf-viewer/src/lib/ngx-extended-pdf-viewer.component.ts#L200

Version info

  • 5.1.0, 5.3.0, 5.4.0-beta.1

Desktop (please complete the following information):

  • Chrome, Nativefier / Electron, but only on production / built dist servers

To Reproduce
Partial example using "Blob" data:

import { HttpClient } from '@angular/common/http';
  public blob: Blob;
  ngOnInit() {
    this.http.get('/assets/pdfs/The Public Domain - Enclosing the Commons of the Mind.pdf', { responseType: 'blob' })
      .subscribe(res => {
        this.blob = res;
      });
  }
  <ngx-extended-pdf-viewer
    [src]="blob"
  >
  </ngx-extended-pdf-viewer>



md5-d8ded7a096ca40c7d4470bc0545db580



```html
     <ngx-extended-pdf-viewer
-      [src]="documentBlob"
+      *ngIf="documentLoaded"
+      [base64Src]="documentBase64"
     ></ngx-extended-pdf-viewer>
Solved Working on it bug

Most helpful comment

Whow. You seem to know what it needs to help a busy open-source developer. How can I talk you into joining the ngx-extended-pdf-viewer team?

Sorry but I already barely have any time to take care of my gitlabci-local project and Android devices system developments :smile: .

The demo has also landed: https://pdfviewer.net/blob

Of course it doesn't show the CSP problem (because the demo runs on a PHP server), but if you display the data requests in the browser's developer tools, you can see there's no data request (apart from the images encoded in the CSS files).

I confirm the demo no longer performs a blob: request.

I upgraded my CSP (helmet) enforced project to [email protected],
and I can confirm the blob: CSP manual rule is no longer required, all good on my side.

Thanks !

All 14 comments

That's unexpected. I wasn't even aware I don't have a BLOB demo on the showcase. Displaying BLOBs was the original use-case. :)

I think the first step is to add a BLOB demo to the showcase. I'm afraid I fairly busy these days, so I can't promise a fast solution.

Best regards,
Stephan

I created a "Blob" type example for extended-pdf-viewer-showcase.

When using a regular Google Chrome browser, we see both these network activities :

- http://localhost:4200/assets/pdfs/The%20Public%20Domain%20-%20Enclosing%20the%20Commons%20of%20the%20Mind.pdf
- blob:http://localhost:4200/ab865de1-c936-45bb-b3f1-61466564c065

The "blob:" internal self-served raw data is induced by the "URL.createObjectURL" API.

I wonder if a refactor to handle "Blob" input types the way I did from the outside with [base64Src] could be a better solution.

Also see stephanrauh/extended-pdf-viewer-showcase#138.

Like I've said over there: thanks, Adrian. You've helped me a lot!

@AdrianDC I can't reproduce the bug using your pull request. Does it occur when you navigate to https://pdfviewer.net/blob?

Alright dived much deeper on my issues and found the origin of the issue.
Our Angular 10 based front runs with a NodeJS 12 back server implemented through express and helmet.

The helmet() wrapper includes a Content Security Policy middleware, which configures the CSP rules strictly.

Here are the configurations I applied to allow blob: network requests :

    this.app.use(
      helmet({
        contentSecurityPolicy: {
          directives: {
            // Default
            ...helmet.contentSecurityPolicy.getDefaultDirectives(),
            // Compatibility: @ajsf (prepare/bus-settings-dialog)
            'script-src': ["'self'", "'unsafe-eval'"],
            // Compatibility: ngx-extended-pdf-viewer (configurator/integration-document)
            'connect-src': ["'self'", 'blob:']
          }
        }
      })
    );

Now I leave it up to you @stephanrauh, there's two options :

  • Expect developers to override the connect-src CSP rule globally in their app, regardless of the origin
  • Refactor the Blob input without createObjectURL and ensure no default CSP violations

Awesome analysis, Adrian!

I'm not familiar with helmet. I assume your code snippet is a workaround?

I'm not sure I can find a better solution. But it looks like a topic worth investigating. If I can't find a solution, I'm going to document your workaround in the showcase.

On a security basis, the code snippet is more a configuration extension for specific purposes than a workaround,
given the fact the CSP directives are meant to be customized to match the strictest requirements of an app.

Helmet is a security middleware for the express framework, which configures various HTTP headers: https://helmetjs.github.io

The configuration I made resolves the issue, but it is 1. mandatory, 2. usually understood after some struggle
and 3. non-specific as it allows blob: beyond "ngx-extended-pdf-viewer" which could be disallowed.

Here's a simple way you'll reproduce the issues I have:

git clone https://github.com/stephanrauh/extended-pdf-viewer-showcase.git
cd ./extended-pdf-viewer-showcase/

npm i
npm run build

cd ./dist/pdf-showcase/
npm install helmet

cat >./server.js <<\EOF
const express = require('express');
const helmet = require("helmet");

const app = express();
const port = 3000;

app.use(helmet());
app.use(express.static(__dirname + '/'));

app.listen(port, () => {
  console.log('');
  console.log(` Listening at http://localhost:${port}`)
  console.log(' Press CTRL-C to stop');
  console.log('');
});
EOF

node ./server.js

Whow. You seem to know what it needs to help a busy open-source developer. How can I talk you into joining the ngx-extended-pdf-viewer team?

I've added your workaround to the library. The feature has landed with version 6.0.0-beta.3. Can you please verify the problem is solved in your project, too?

Best regards,
Stephan

The demo has also landed: https://pdfviewer.net/blob

Of course it doesn't show the CSP problem (because the demo runs on a PHP server), but if you display the data requests in the browser's developer tools, you can see there's no data request (apart from the images encoded in the CSS files).

Whow. You seem to know what it needs to help a busy open-source developer. How can I talk you into joining the ngx-extended-pdf-viewer team?

Sorry but I already barely have any time to take care of my gitlabci-local project and Android devices system developments :smile: .

The demo has also landed: https://pdfviewer.net/blob

Of course it doesn't show the CSP problem (because the demo runs on a PHP server), but if you display the data requests in the browser's developer tools, you can see there's no data request (apart from the images encoded in the CSS files).

I confirm the demo no longer performs a blob: request.

I upgraded my CSP (helmet) enforced project to [email protected],
and I can confirm the blob: CSP manual rule is no longer required, all good on my side.

Thanks !

@AdrianDC You're referring to this project? https://pypi.org/project/gitlabci-local/

Looks like you've been busy this year. If you'd like to write about it on https://beyondjava.net, just tell me. Or send me a couple of keywords so I can write the article myself!

Hi ! Sorry for the late reply, yes this is gitlabci-local.
Been working on the project quite a bit lately, expanding supported environments and features.
Feel free to share it if you find it interesting, everything is documented on the project itself and in the sources.

I just hope I manage to find a couple of spare minutes... currently, I'm writing a series of articles on GraalVM for a print magazin, and that's much more work than expected! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ekselys picture ekselys  路  5Comments

rscherer picture rscherer  路  7Comments

Prasanth-FrontendDeveloper picture Prasanth-FrontendDeveloper  路  7Comments

i7i5 picture i7i5  路  3Comments

mkanwar picture mkanwar  路  6Comments