Search code examples
angulariframesanitizeangular-dom-sanitizer

Angular sanitizing url to be used in an iframe's src


I'm trying to construct an url to pass it inside the src attributes of an iframe. But I always get the exception unsafe value used in a resource URL context and I'm struggling to understand how to correctly sanitize the url.

I could make it work with domSanitizer.bypassSecurityTrustResourceUrl(myCustomUrlAsString) but from what I understand, by doing so, I'm just disabling the security. Even tho it could be acceptable as the url is not constructed with any user input, I want to understand how the sanitization work.

My ng component code:

export class MyAngularComponent implements OnInit {
   public url: SafeResourceUrl | null;
   
   constructor(private domSanitizer: DomSanitizer) {}

   ngOnInit() {
       const url = new URL('https://example.org?param1=foo');
       this.url = this.domSanitizer.sanitize(SecurityContext.URL, url.toString());
   }
}

My template: <iframe [src]="url" width="100%" height="100%"></iframe>

When checking the sanitized value, it's just a string or that same url. But the template rendering triggers the exception. Shouldn't the sanitize function return a Safe Url to avoid this exception? Or should I had the bypassSecurityTrustResourceUrl in any case after the sanitize?

Tx for the help


Solution

  • Let say we are passing invalid URL to bypassSecurityTrustResourceUrl directly, It will assume we are passing valid url and return SafeResourceUrl object without throwing any error.

    Example

    const invalidURL = `javascript:alert('Moar XSS!')`;
    const url = this.domSanitizer.sanitize(SecurityContext.URL,invalidURL);
    //It will skip validing URL and will not throw any error.
    

    sanitize method will add additional check to make the url safe to use.

    const invalidURL = `javascript:alert('Moar XSS!')`;
    const url = this.domSanitizer.sanitize(SecurityContext.URL, url.toString());
    //This additional check will ensure the above string is invalid string.
    this.domSanitizer.bypassSecurityTrustResourceUrl(url);
    

    It is better practice to use the sanitize URL before passing it to the bypassSecurityTrustResourceUrl method to make the url safe.

    const url = this.domSanitizer.sanitize(SecurityContext.URL, url.toString());
    this.url = this.domSanitizer.bypassSecurityTrustResourceUrl(url);