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.
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
Plunker
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>
Plunker
If you use embed tag this might be interesting for you:
how with angular2 rc.6 disable sanitize on embed html tag which display pdf
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';
Plunker sample
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);
}
}
This works me to Angular 5.2.0
fileName.Component.ts
import { Component, OnInit, Input } from '#angular/core';
import { DomSanitizer, SafeResourceUrl } from '#angular/platform-browser';
#Component({
selector: 'app-sample',
templateUrl: './fileName.component.html',
styleUrls: ['./fileName.component.scss']
})
export class FileName implements OnInit {
#Input()
url: string = "https://www.mmlpqtpkasjdashdjahd.com";
urlSafe: SafeResourceUrl;
constructor(public sanitizer: DomSanitizer) { }
ngOnInit() {
this.urlSafe= this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
}
}
fileName.Component.html
<iframe width="100%" height="100%" frameBorder="0" [src]="urlSafe"></iframe>
thats all folks!!!
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.
<img [src]="sanitizer.bypassSecurityTrustResourceUrl(country.flag)"
height="20" width="20" alt=""/>
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.
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>
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');
}
}
I'll share this solution even if this is NOT best practice, but it happened to me once that we were not allowed to use the this.domSanitizer.bypassSecurityTrustResourceUrl(url) solution because of an automatic security warning that stopped the CI/CD pipelines.
#Component({
template: '<iframe #iframeRef></iframe>'
})
export class UnsafeUrlBypassIframeSampleComponent implements AfterViewInit {
#ViewChild('iframeRef') iframe: ElementRef<HTMLIFrameElement>;
constructor(private renderer: Renderer2) {}
ngAfterViewInit() {
const MY_UNSAFE_URL = '/path/to/something';
this.renderer.setProperty(this.iframe.nativeElement, 'src', MY_UNSAFE_URL);
}
}
If it is the case that you need to bypass Angular security systems, and this will inevitably lead to vulnerabilities, it is best to do it explicitly.
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>
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 ;)
Related
I am trying to add something to the constructor of one of my Angular components, however, anytime I put something in the constructor, it renders the entire page blank - getting rid of all of the other components and displaying just the background.
For example - this will work.
TS
#Component({
selector: 'app-cardboxes',
templateUrl: './cardboxes.component.html',
styleUrls: ['./cardboxes.component.scss']
})
export class CardboxesComponent implements OnInit {
constructor() { }
ngOnInit(): void {}
}
And this will render completely blank - removing everything, even the other components.
TS
#Component({
selector: 'app-cardboxes',
templateUrl: './cardboxes.component.html',
styleUrls: ['./cardboxes.component.scss']
})
export class CardboxesComponent implements OnInit {
constructor(private dialog: MatDialog) { }
ngOnInit(): void {}
}
For the record, it doesn't matter what is put in the constructor - it is the same result every time. The Chrome terminal says that there is a NullInjectorError - No provider for MatDialog
Is there a reason for this, or an easy solution? I do not understand why this is happening and I really need to be able to use the constructors. Do I have to make another import somewhere? Is there a configuration I am missing?
You are trying to use angular materials. Please use this comand in console.
npm i #angular/material
Open app.module and
NgModule ({....
imports: [...,
MatSliderModule,
…]
Items adsed in constructor should be imported in module
I want to load the external jsp page content as template in my component in angular 6 application.
#Component({
selector: 'app-conrequest',
templateUrl:'mydomain.com:port/utils/registerUser.jsp',
styleUrls: ['./conrequest.component.css']
})
In the above code, I have mentioned the jsp page url, which I want to load as a template.
Please help me on this.
Thanks,
Suresh
First of all whichever external link you are using it should "return" something.
If there is no information in return it will always gives you an error.
Lets begin your answer...
Step 1- First you need to import HttpClient and Map
import { HttpClient } from '#angular/common/http';
import 'rxjs/add/operator/map';
Step 2- and your #Component decorator should look like this
#Component({
selector: 'my-template',
template: `<div [innerHtml]="myTemplate">
</div> `})
Step 3- in your class you can import your external template like...
export class TestComponent {
private myTemplate: any = '';
constructor(http: HttpClient) {
http.get('www.abc.com/index.html', {responseType: 'text'}).subscribe(data => this.myTemplate = data);
}
}
Step 4 - Also import httpClient in RootModule
imports: [
...
...
HttpClientModule
],
That's it. Try with yours.
Thanks
Sunil Sain
I have to implement autocomplete for a text input that takes addresses/locations in Angular 4.
I found this package on Google, https://tanoy009.github.io/ng4-geoautocomplete/, but I am not sure where to place the settings part of example3 in my own code. This is what I have so far:
export class TestComponent {
apiAddress: string = "";
#Output() notify: EventEmitter<any> = new EventEmitter<any>();
autoCompleteCallback1(selectedData: any) {
this.apiAddress = selectedData.description;
this.notify.emit(this.apiAddress);
}
You should look at the documentation. It's very clear.
https://github.com/tanoy009/ng4-geoautocomplete#installation
Installation
Install through npm:
npm install --save ng4-geoautocomplete Then include in your apps
module:
import { Component, NgModule } from '#angular/core'; import {
Ng4GeoautocompleteModule } from 'ng4-geoautocomplete';
#NgModule({
imports: [
Ng4GeoautocompleteModule.forRoot()
]
})
export class MyModule{}
Add google place script in your main file generally referred to
'index.html' (Optional if you want to use google services).
<script type="text/javascript"
src="https://maps.google.com/maps/api/js?sensor=true&key=XXReplace
this with valid keyXX&libraries=places&language=en-US"></script>
Finally use in one of your apps components:
import { Component } from '#angular/core';
#Component({ template: '<ng4geo-autocomplete
(componentCallback)="autoCompleteCallback1($event)"></ng4geo-
autocomplete>'
})
export class MyComponent {
autoCompleteCallback1(selectedData:any) {
//do any necessery stuff.
}
}
UPDATE: The next part of the answer is an update placed here to answer the question in the comment section.
The following links show the code for the demo you linked. This will tell you where to put the settings. You basically create settings in your component's typescript file and then use them in the html.
TypeScript
public userSettings2: any = {
showRecentSearch: false,
geoCountryRestriction: ['in'],
searchIconUrl: 'http://downloadicons.net/sites/default/files/identification-search-magnifying-glass-icon-73159.png'
};
HTML
<ng4geo-autocomplete [userSettings]="userSettings2" (componentCallback)="autoCompleteCallback2($event)"></ng4geo-autocomplete>
https://github.com/tanoy009/ng4-geoautocomplete/blob/master/demo/demo.component.ts
https://github.com/tanoy009/ng4-geoautocomplete/blob/master/demo/demo.component.html
My problem is the following, I get as a response from a service an entire HTML page that I should display back t the user. Now this is an issue for Angular since it thinks I might be a victim of cross site scripting if I do that. The source I get the HTML from is trusted so I wanted to white list it or bypass the sanitizer in some way and render the view to the user.
The problem I ran into is that the file I get also contains 'style' and 'script' tags for manipulating the dom, and no matter how I place the bypass function calls something gets caught and the entire thing doesn't render properly. Is there any way I could maybe separate the HTML file clear it and then put it back together or something else?
Try this:
import { DomSanitizer } from '#angular/platform-browser';
constructor(private sanitizer: DomSanitizer) { }
//where you want to use the unsafe html
const sanitizedHtml = this.sanitizer.bypassSecurityTrustResourceUrl(html);
What you can do, but goes against the Angular principle, is to append the html markup to the innerhtml of your component or the DOM using ElementRef from
#angular/core.
Sample appcomponent:
import { Component, ElementRef } from '#angular/core';
#Component({
selector: 'my-app',
template: ``,
})
export class AppComponent {
private htmlTemplate = `
<div>Loading template</div>
<script type="text/javascript">
console.log('loaded');
</script>
`;
constructor(private elementRef: ElementRef) { }
ngAfterViewInit() {
let elem: Element = this.elementRef.nativeElement;
elem.innerHTML = this.htmlTemplate;
}
}
Styles like
<div [style.background-image]="\'url(\' + image + \')\'">Background</div>
<div [style.transform]="rotate(7deg)"
are not added anymore
update (2.0.0 final)
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name: 'safeHtml'})
export class SafeHtml implements PipeTransform {
constructor(private sanitizer:DomSanitizer){}
transform(html) {
return this.sanitizer.bypassSecurityTrustStyle(html);
// return this.sanitizer.bypassSecurityTrustHtml(html);
// return this.sanitizer.bypassSecurityTrustScript(html);
// return this.sanitizer.bypassSecurityTrustUrl(html);
// return this.sanitizer.bypassSecurityTrustResourceUrl(html);
}
}
See also https://angular.io/api/platform-browser/DomSanitizer
<div [innerHTML]="someHtml | safeHtml"
update
DomSanitizationService is going to be renamed to DomSanitizer in RC.6
original
This should be fixed in RC.2
See also Angular2 Developer Guide - Security
Angular2 intruduced sanitization of CSS values and property binding like [innerHTML]=... and [src]="..." in RC.1
See also https://github.com/angular/angular/issues/8491#issuecomment-217467582
The values can be marked as trusted by using DomSanitizer.bypassSecurityTrustStyle(...)
import {DomSanitizer} from '#angular/platform-browser';
...
constructor(sanitizer: DomSanitizationService) {
this.backgroundImageStyle = sanitizer.bypassSecurityTrustStyle('url(' + this.image + ')');
// for HTML
// this.backgroundImageStyle = sanitizer.bypassSecurityTrustHtml(...);
}
and binding to this value instead the untrusted plain string.
This can also be wrapped in a pipe like
#Pipe({name: 'safeStyle'})
export class Safe {
constructor(private sanitizer:Sanitizer){}
transform(style) {
return this.sanitizer.bypassSecurityTrustStyle(style);
// return this.sanitizer.bypassSecurityTrustHtml(style);
// return this.sanitizer.bypassSecurityTrustScript(value);
// return this.sanitizer.bypassSecurityTrustUrl(value);
// return this.sanitizer.bypassSecurityTrustResourceUrl(value);
}
}
<div [ngStyle]="someStyle | safeStyle"></div>
with
someHtml = `click to see the awesome`;
is still working though :-[ (it's work in progress)
Plunker example (Angular 2.0.0-rc-1)
See also Angular 2 Security Tracking Issue
and https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizer-class.html
Hint about {{...}}
Sanitized content can't be bound using prop="{{sanitizedContent}}" because {{}} stringyfies the value before it is assigned which breaks sanitization.
Bypassing sanitizer to trust any content can be a security concern. Since Angular is not a dedicated sanitizing library, it is overzealous towards suspicious content to not take any risks. It removes almost all attributes, for example. You can delegate sanitizing to a dedicated library — DOMPurify. Here's a wrapper library I've made to easily use DOMPurify with Angular.
https://github.com/TinkoffCreditSystems/ng-dompurify
It also has a pipe to declaratively sanitize HTML:
<div [innerHtml]="value | dompurify"></div>
One thing to keep in mind is DOMPurify is great for sanitizing HTML/SVG, but not CSS. So you can provider Angular's CSS sanitizer to handle CSS:
import {NgModule, ɵ_sanitizeStyle} from '#angular/core';
import {SANITIZE_STYLE} from '#tinkoff/ng-dompurify';
#NgModule({
// ...
providers: [
{
provide: SANITIZE_STYLE,
useValue: ɵ_sanitizeStyle,
},
],
// ...
})
export class AppModule {}
It's internal — hense ɵ prefix, but this is how Angular team use it across their own packages as well anyway.