terikon / cordova-plugin-photo-library

Maintainer needed. Please contact if you're using this library in your project
MIT License
149 stars 296 forks source link

CSP and Ionic 2 (Angular 2), 'Refused to load the image "unsafe:cdvphotolibrary"' #15

Closed dnmd closed 7 years ago

dnmd commented 7 years ago

Excellent plugin, I hope it becomes part of the native plugins soon, I'll contribute where possible (and will look into making the wrapper)!

Just a small issue, I think it is related to CSP and Angular 2 (thus Ionic 2), but I can't get thumbnails to be displayed without sanitizing the URL's. When doing so, the whole <meta> tag is not required anymore, therefore it feels wrong but it is the only way I got it working. Maybe I'm missing something... I posted my current solution below.

<!-- without sanitizing, the following error shows up in the console -->
Refused to load the image 'unsafe:cdvphotolibrary://thumbnail?...height=384&quality=0.8' because it violates the following Content Security Policy directive: "img-src 'self' data: blob: cdvphotolibrary:".
<!-- not required when sanitizing your URL's, therefore it feels "wrong" -->
  <meta http-equiv="Content-Security-Policy" 
        content="default-src 'self' data: gap: https://ssl.gstatic.com; 
                 style-src 'self' 'unsafe-inline'; 
                 img-src 'self' data: blob: cdvphotolibrary:"> 
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';

...

list: Array<string> = new Array();
constructor( private ds: DomSanitizer) { }

...

var self = this;
cordova.plugins.photoLibrary.getLibrary(
      function (library) {

        library.forEach(function (libraryItem) {
          // sanitize, else Angular 2 prepends: "unsafe:"
          let url: SafeUrl = self.ds.bypassSecurityTrustUrl(libraryItem.thumbnailURL);
          self.list.push(<string>url);

        });

      },
      function (err) { },
      {
        thumbnailWidth: 512,
        thumbnailHeight: 384,
        quality: 0.8
      }
);
viskin commented 7 years ago

Nice finding. I don't use ng2 in my current project, so I cannot tell exactly what's going on here, but... It's interesting why DomSanitizer decides to add unsafe: prefix to cdvphotolibrary protocol? cordova-plugin-file uses cdvfile:// protocol, do you use it in your app? I wonder if cdvfile:// also needs to be manually trusted with ng2? Anyway, if you will use PipeTransform to perform bypassSecurityTrustUrl on cdvphotolibrary urls, in a way described here, will it work and will it be convenient enough? If so, we can recommend this solution in README.

metalaureate commented 7 years ago

@viskin Apologies if this is not the same issue--I'm using Angular 1.5 and I get this error when I try to construct the url:

Refused to load unsafe:cdvphotolibrary://photo?photoId=5F347FD6-7D84-4208-BA29-BD4C5735525D%2FL0%2F001 because it does not appear in the img-src directive of the Content Security Policy.

My CSP tag looks like:

<meta http-equiv="Content-Security-Policy"
         content="default-src 'self' data: gap: https://ssl.gstatic.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: cdvphotolibrary:">
dnmd commented 7 years ago

@metalaureate, as explained, Angular 1 and 2 will always sanitize data that gets injected into the DOM, it will not respect any CSP rules present, thus also in Angular 1 you need to whitelist the cdvphotolibrary protocol like so:

var app = angular
    .module('myApp', [])
    .config([
        '$compileProvider',
        function ($compileProvider) {
            $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|cdvphotolibrary):/);
            // Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)
        }
    ]);

source

dnmd commented 7 years ago

Angular treats all values as untrusted by default. When a value is inserted into the DOM from a template, via property, attribute, style, class binding, or interpolation, Angular sanitizes and escapes untrusted values (source)

@viskin, the cdvfile:// and cdvphotolibrary:// 'prefixes' are (indeed) both treated as unsafe, I've tested both plugins. The CSP meta tag can be seen as the first layer of defense, but as we've seen, Angular has its own.

So as a note to the use of Ionic 2, one can construct a Pipe, to sanitize the URL's used in this plugin. Another solution might be returning a blob or ArrayBuffer (instead of URL's), as implemented in this cordova-plugin-photos.

@Pipe({name: 'safeUrl'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(url) {
    return this.sanitizer.bypassSecurityTrustUrl(url);
  }
}
@Component({
   selector: 'app',
   template: '<img [src]="url | safeUrl"></div>',
   pipes: [
      SanitizeHtml
   ]
})

export class AppComponent{

    public url: string = 'placeholder.jpg';

    constructor() {
      // fetch thumbnail URL's
      this.url = libraryItem.thumbnailURL;
    }

} 
viskin commented 7 years ago

Great, I will add this info to README. Thank you.

@dnmd, we already support returning blob instead of url with photoLibrary.getThumbnail and photoLibrary.getPhoto.

arberkryeziu commented 7 years ago

I have some issues with sanatization. The guideline for Angular 2 in the Readme is not correct. ... @Component({ selector: 'app', template: '<img [src]="url | safeUrl"></div>', pipes: [ SafeUrl ] }) ... With my little research , I saw that Pipes cannot be declared inside component anymore. They should be declared in NgModules . Notice also the closing tag inside template. It should be img instead of div.

However, even after doing that, I get SafeValue must use [property]=binding: cdvphotolibrary://photo?photoId=65E0377C-1838-4FC8-990F-34801BA0F6A9%2FL0%2F001 (see http://g.co/ng/security#xss)

Does anybody else has this issue in ios ?

viskin commented 7 years ago

@arberK Thanks, I updated the readme.

giacomodeliberali commented 6 years ago

Have the same issue of @arberK. @viskin, how can the bypass be achieved?

pratikjain93 commented 6 years ago

Can anybody give the syntax for IONIC 1 i.e angular 1 as i have project running in Angular 1. Any help is highly appreciated.