81

Styles like

<div [style.background-image]="\'url(\' + image + \')\'">Background</div>
<div [style.transform]="rotate(7deg)"

are not added anymore

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567

2 Answers2

126

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 = `<a href="#" onClick="alert(document.cookie);">click to see the awesome</a>`;

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.

Chris O'Kelly
  • 1,863
  • 2
  • 18
  • 35
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • See also http://stackoverflow.com/questions/37238757/angular2-rc1-sanitizer-inserts-double-quotes-inside-styles-breaking-it – Günter Zöchbauer May 15 '16 at 15:12
  • For some reason, when I try to use this service, the dependency injection doesn't work. Instead of getting the service implementation, I get abstract service (which is an empty object). Do you have any idea why this happens? Am I missing something? – Yaron Schwimmer Jun 22 '16 at 11:35
  • @yarons can you please create a new question and add some code that demonstrates what you're actually doing. If possible a Plunker that allows to reproduce. – Günter Zöchbauer Jun 22 '16 at 11:41
  • @GünterZöchbauer the problem is that I can't reproduce it. In Plunker it [works fine](http://plnkr.co/edit/d3iWiUnUEXfgO555Z9VZ). Only when I run my application locally it fails. I thought maybe it's something you encountered. But you are right, I should open a new question for this. – Yaron Schwimmer Jun 22 '16 at 11:57
  • Try purging `npm_modules` and reinstall. I saw that mentioned several times recently that it fixes weird issues. – Günter Zöchbauer Jun 22 '16 at 12:02
  • it is not fixed on rc.2 – albanx Jul 07 '16 at 08:52
  • Some styles are not supposed to be added without explicity `bypassSecurityXxx` – Günter Zöchbauer Jul 07 '16 at 10:15
  • @GünterZöchbauer Just a question, shouldn't your `SafeHtml` implement `PipeTransform`? – SrAxi May 27 '17 at 16:49
  • 2
    @SrAxi you are right. Back then it worked fine without as well – Günter Zöchbauer May 27 '17 at 18:03
  • Good idea, but ruins everything when you have to use aother part of the code – fsalazar_sch Dec 10 '22 at 01:39
1

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.

waterplea
  • 3,462
  • 5
  • 31
  • 47