How to set <iframe src="..."> without causing `unsafe value` exception?
AngularAngular Problem Overview
I am working on a tutorial involving the setting of an iframe
src
attribute:
<iframe width="100%" height="300" src="{{video.url}}"></iframe>
This throws an exception:
Error: unsafe value used in a resource URL context
at DomSanitizationServiceImpl.sanitize...
I have already tried using bindings with [src]
with no success.
Angular Solutions
Solution 1 - Angular
Update v8
Below answers work but exposes your application to XSS security risks!.
Instead of using this.domSanitizer.bypassSecurityTrustResourceUrl(url)
, it is recommended to use this.domSanitizer.sanitize(SecurityContext.URL, url)
Update
For RC.6^ version use DomSanitizer
And a good option is using pure pipe for that:
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer} from '@angular/platform-browser';
@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
constructor(private domSanitizer: DomSanitizer) {}
transform(url) {
return this.domSanitizer.bypassSecurityTrustResourceUrl(url);
}
}
remember to add your new SafePipe
to the declarations
array of the AppModule. (as seen on documentation)
@NgModule({
declarations : [
...
SafePipe
],
})
html
<iframe width="100%" height="300" [src]="url | safe"></iframe>
If you use embed
tag this might be interesting for you:
Old version RC.5
You can leverage DomSanitizationService
like this:
export class YourComponent {
url: SafeResourceUrl;
constructor(domSanitizationService: DomSanitizationService) {
this.url = domSanitizer.bypassSecurityTrustResourceUrl('your url');
}
}
And then bind to url
in your template:
<iframe width="100%" height="300" [src]="url"></iframe>
Don't forget to add the following imports:
import { SafeResourceUrl, DomSanitizationService } from '@angular/platform-browser';
Solution 2 - Angular
This one works for me.
import { Component,Input,OnInit} from '@angular/core';
import {DomSanitizer,SafeResourceUrl,} from '@angular/platform-browser';
@Component({
moduleId: module.id,
selector: 'player',
templateUrl: './player.component.html',
styleUrls:['./player.component.scss'],
})
export class PlayerComponent implements OnInit{
@Input()
id:string;
url: SafeResourceUrl;
constructor (public sanitizer:DomSanitizer) {
}
ngOnInit() {
this.url = this.sanitizer.bypassSecurityTrustResourceUrl(this.id);
}
}
Solution 3 - Angular
This works me to Angular 5.2.0
sarasa.Component.ts
import { Component, OnInit, Input } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Component({
selector: 'app-sarasa',
templateUrl: './sarasa.component.html',
styleUrls: ['./sarasa.component.scss']
})
export class Sarasa implements OnInit {
@Input()
url: string = "https://www.mmlpqtpkasjdashdjahd.com";
urlSafe: SafeResourceUrl;
constructor(public sanitizer: DomSanitizer) { }
ngOnInit() {
this.urlSafe= this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
}
}
sarasa.Component.html
<iframe width="100%" height="100%" frameBorder="0" [src]="urlSafe"></iframe>
thats all folks!!!
Solution 4 - Angular
constructor(
public sanitizer: DomSanitizer, ) {
}
I had been struggling for 4 hours. the problem was in img tag. When you use square bracket to 'src' ex: [src]. you can not use this angular expression {{}}. you just give directly from an object example below. if you give angular expression {{}}. you will get interpolation error.
-
first i used ngFor to iterate the countries
*ngFor="let country of countries"
-
second you put this in the img tag. this is it.
Solution 5 - Angular
I ran into this issue as well, but in order to use a safe pipe in my angular module, I installed the safe-pipe npm package, which you can find here. FYI, this worked in Angular 9.1.3, I haven't tried this in any other versions of Angular. Here's how you add it step by step:
-
Install the package via npm install safe-pipe or yarn add safe-pipe. This will store a reference to it in your dependencies in the package.json file, which you should already have from starting a new Angular project.
-
Add SafePipeModule module to NgModule.imports in your Angular module file like so:
import { SafePipeModule } from 'safe-pipe'; @NgModule({ imports: [ SafePipeModule ] }) export class AppModule { }
-
Add the safe pipe to an element in the template for the Angular component you are importing into your NgModule this way:
<element [property]="value | safe: sanitizationType"></element>
- Here are some specific examples of the safePipe in an html element:
<div [style.background-image]="'url(' + pictureUrl + ')' | safe: 'style'" class="pic bg-pic"></div>
<img [src]="pictureUrl | safe: 'url'" class="pic" alt="Logo">
<iframe [src]="catVideoEmbed | safe: 'resourceUrl'" width="640" height="390"></iframe>
<pre [innerHTML]="htmlContent | safe: 'html'"></pre>
Solution 6 - Angular
All answers seem wrong to be honest. Using this.sanitizer.bypassSecurityTrustResourceUrl(url)
only bypasses the security and treats the url as a SafeResourceUrl
. However, given url may still be malicious resulting in security violations. Docs say so too: https://angular.io/api/platform-browser/DomSanitizer#bypassSecurityTrustResourceUrl
A solution would be to call sanitizer
first and the pass the sanitizer
return value to the bypassSecurityTrustResourceUrl
like this:
this.sanitizer.bypassSecurityTrustResourceUrl(this.sanitizer.sanitize(SecurityContext.URL, url))
This way you sanitize any malicious code and then bypass the security denoting this is indeed a safe url.
Solution 7 - Angular
This works for me
I defined an id in the iframe
<iframe id="embeddedPage"></iframe>
and in the component I used this code
export class YourComponent implements OnInit {
constructor() {}
ngOnInit(): void {
const iframe = document.getElementById('embeddedPage') as HTMLIFrameElement;
iframe.contentWindow.location.replace('your url');
}
}
Solution 8 - Angular
> I usually add separate safe pipe reusable component as following
# Add Safe Pipe
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({name: 'mySafe'})
export class SafePipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {
}
public transform(url) {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
}
# then create shared pipe module as following
import { NgModule } from '@angular/core';
import { SafePipe } from './safe.pipe';
@NgModule({
declarations: [
SafePipe
],
exports: [
SafePipe
]
})
export class SharedPipesModule {
}
# import shared pipe module in your native module
@NgModule({
declarations: [],
imports: [
SharedPipesModule,
],
})
export class SupportModule {
}
<!-------------------
call your url (`trustedUrl` for me) and add `mySafe` as defined in Safe Pipe
---------------->
<div class="container-fluid" *ngIf="trustedUrl">
<iframe [src]="trustedUrl | mySafe" align="middle" width="100%" height="800" frameborder="0"></iframe>
</div>
Solution 9 - Angular
Congratulation ! ¨^^ I have an easy & efficient solution for you, yes!
<iframe width="100%" height="300" [attr.src]="video.url"></iframe
> [attr.src] instead of src > "video.url" and not {{video.url}}
Great ;)