Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sanitize input in Angular2 [duplicate]

I am trying to get third-party (potentially unsafe) html content from my database and insert it into my html document.

How do I safely do that (Protection against XSS) ?

In Angular1.x there used to be $sce to sanitize input, how do I do that in Angular2 ? As far as I understand, Angular2 automatically sanitizes it by default, is that correct ?

Something like this will not work:

<div class="foo">     {{someBoundValueWithSafeHTML}} // I want HTML from db here </div> 
like image 977
the_critic Avatar asked Dec 25 '15 22:12

the_critic


People also ask

How sanitization works in Angular?

Sanitization and security contextslinkSanitization is the inspection of an untrusted value, turning it into a value that's safe to insert into the DOM. In many cases, sanitization doesn't change a value at all. Sanitization depends on context: A value that's harmless in CSS is potentially dangerous in a URL.

Does angular sanitize user input?

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. Sanitization modifies the input, turning it into a value that is safe to insert into the DOM.

Does angular innerHtml sanitize?

Angular comes with a built-in html sanitizer DomSanitizer , as a security feature, thats used whenever you use [innerHtml] .

How do you sterilize strings?

Use the sanitize() Method to Sanitize String in JavaScript It should be used when the data is already available as DOM nodes, such as when sanitizing a Document instance in a frame. The default sanitizer() configuration automatically strips out XSS-relevant input, including script tags, custom elements, and comments.


1 Answers

To insert normal HTML into your angular2 app, you can use the [innerHtml] directive.

<div [innerHtml]="htmlProperty"></div> 

This is not going to work with HTML which has its own components and directives, at least not in the way you'd expect it.

If however you do get an unsafe html warning you should trust the HTML first before injecting it. You have to use the DomSanitizer for such a thing. For instance, an <h3> element is considered safe. An <input> element is not.

export class AppComponent  {      private _htmlProperty: string = '<input type="text" name="name">';      public get htmlProperty() : SafeHtml {        return this.sr.bypassSecurityTrustHtml(this._htmlProperty);     }      constructor(private sr: DomSanitizer){} } 

And have your template stay the same as this:

<div [innerHtml]="htmlProperty"></div> 

A little heads-up though:

WARNING: calling this method with untrusted user data exposes your application to XSS security risks!

If you plan on using this technique more, you can try to write a @Pipe to fulfill this task.

import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser';  @Pipe({     name: 'trustHtml' }) export class TrustHtmlPipe implements PipeTransform  {        constructor(readonly sr: DomSanitizer){}       transform(html: string) : SafeHtml {       return this.sr.bypassSecurityTrustHtml(html);     }  }  

If you have a pipe like this, your AppComponent will change to this. Don't forget to add the pipe to your declarations array of your NgModule:

@Component({    selector: 'app',    template: `<div [innerHtml]="htmlProperty | trustHtml"></div>` }) export class AppComponent{      public htmlProperty: string = '<input type="text" name="name">';  }  

Or you can write a @Directive to do the same:

@Directive({    selector: '[trustHtml]' }) export class SanitizeHtmlDirective {      @Input()     public set trustHtml(trustHtml: string) {       if (this._trustHtml !== trustHtml) {         this._trustHtml = trustHtml;         this.innerHtml = this.sr.bypassSecurityTrustHtml(this.trustHtml);       }     }      @HostBinding('innerHtml')     innerHtml?: SafeHtml;      private _trustHtml: string;      constructor(readonly sr: DomSanitizer){} } 

If you have a directive like this, your AppComponent will change to this. Don't forget to add the directive to your declarations array of your NgModule:

@Component({    selector: 'app',    template: `<div [trustHtml]="htmlProperty"></div>` }) export class AppComponent{      public htmlProperty: string = '<input type="text" name="name">';  }  
like image 149
Poul Kruijt Avatar answered Sep 30 '22 07:09

Poul Kruijt