ADVERTENCIA: desinfectar la URL de valor de estilo inseguro

107

Quiero configurar la imagen de fondo de un DIV en una plantilla de componente en mi aplicación Angular 2. Sin embargo, sigo recibiendo la siguiente advertencia en mi consola y no obtengo el efecto deseado ... No estoy seguro de si la imagen de fondo CSS dinámica se está bloqueando debido a restricciones de seguridad en Angular2 o si mi plantilla HTML está rota.

Esta es la advertencia que veo en mi consola (he cambiado mi URL de imagen a /img/path/is/correct.png:

ADVERTENCIA: desinfectar la URL del valor de estilo inseguro (SafeValue debe usar [propiedad] = enlace: /img/path/is/correct.png (ver http://g.co/ng/security#xss )) (ver http: // g.co/ng/security#xss ).

Lo que pasa es que desinfecciono lo que se inyecta en mi plantilla usando DomSanitizationServiceen Angular2. Aquí está mi HTML que tengo en mi plantilla:

<div>
    <div>
        <div class="header"
             *ngIf="image"
             [style.background-image]="'url(' + image + ')'">
        </div>

        <div class="zone">
            <div>
                <div>
                    <h1 [innerHTML]="header"></h1>
                </div>
                <div class="zone__content">
                    <p
                       *ngFor="let contentSegment of content"
                       [innerHTML]="contentSegment"></p>
                </div>
            </div>
        </div>
    </div>
</div>

Aquí está el componente ...

Import {
    DomSanitizationService,
    SafeHtml,
    SafeUrl,
    SafeStyle
} from '@angular/platform-browser';

@Component({
               selector: 'example',
               templateUrl: 'src/content/example.component.html'
           })
export class CardComponent implements OnChanges {

    public header:SafeHtml;
    public content:SafeHtml[];
    public image:SafeStyle;
    public isActive:boolean;
    public isExtended:boolean;

    constructor(private sanitization:DomSanitizationService) {
    }

    ngOnChanges():void {
        map(this.element, this);

        function map(element:Card, instance:CardComponent):void {
            if (element) {
                instance.header = instance.sanitization.bypassSecurityTrustHtml(element.header);

                instance.content = _.map(instance.element.content, (input:string):SafeHtml => {
                    return instance.sanitization.bypassSecurityTrustHtml(input);
                });

                if (element.image) {
                    /* Here is the problem... I have also used bypassSecurityTrustUrl */ 
                    instance.image = instance.sanitization.bypassSecurityTrustStyle(element.image);
                } else {
                    instance.image = null;
                }

            }
        }
    }
}

Tenga en cuenta que cuando acabo de enlazar a la plantilla usando [src] = "image", por ejemplo:

<div *ngIf="image">
    <img [src]="image">
</div>

y imagese pasó usando bypassSecurityTrustUrltodo parecía funcionar bien ... ¿alguien puede ver lo que estoy haciendo mal?

Mark Sandman
fuente
¿Obtuviste una solución a tu pregunta? Tengo exactamente el mismo problema y sigo intentando encontrar una solución. ¡Gracias por adelantado!
SK.

Respuestas:

112

Tienes que envolver toda la urldeclaración en bypassSecurityTrustStyle:

<div class="header" *ngIf="image" [style.background-image]="image"></div>

Y tiene

this.image = this.sanitization.bypassSecurityTrustStyle(`url(${element.image})`);

De lo contrario, no se considera una propiedad de estilo válida.

Poul Kruijt
fuente
1
PierreDuc, ¿alguna palabra de sabiduría para cuando la imagen de fondo se omite como se indicó anteriormente, pero luego Angular2 la ignora en silencio? Puedo publicar una nueva pregunta, pero creo que es bastante relevante para su respuesta.
David Pfeffer
@DavidPfeffer Es difícil juzgar dónde van las cosas mal sin ver ningún código :) Utilizo este código en el último angular2 y todavía está funcionando ..
Poul Kruijt
1
Me lo imaginé. Después de omitir la desinfección, si el valor no es válido, Angular2 lo ignora en silencio.
David Pfeffer
Debe utilizar ngStyle y funcionará sin interferir con la desinfección.
yglodt
Trabajó para mí en Angular8. Creo que desinfectar es mejor ... existe por una razón. @yglodt.
Sean Halls
67

Use esto, <div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>esto resolvió el problema para mí.

iRedia Ebikade
fuente
Seguro y sencillo.
Kenmore
Gracias por tus amables palabras @Kenmore. Me alegro de poder ser de ayuda. Salud.
iRedia Ebikade
@ Sammy-RogersGeek ¿puedo escribir el mismo código en la etiqueta de imagen?
Arjun
¡Me salvas el día!
VAdaihiep
Elocuente. Gracias.
Equipo Mindsect
52

Si imagen de fondo con degradado lineal ( *ngFor)

Ver:

<div [style.background-image]="getBackground(trendingEntity.img)" class="trending-content">
</div>

Clase:

import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';

constructor(private _sanitizer: DomSanitizer) {}

getBackground(image) {
    return this._sanitizer.bypassSecurityTrustStyle(`linear-gradient(rgba(29, 29, 29, 0), rgba(16, 16, 23, 0.5)), url(${image})`);
}
Swapnil Patwa
fuente
1
me salvaste el día
Thamaraiselvam
1
Funciona perfectamente :))
Abhijit Srivastava
@AbhijitSrivastava Escribí thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url ($ {thumbnail}) )y [style.backgroundImage]="thumbnailMediumIcon". ¿Qué versión de Angular usaste? También probé background-image. ¿Esto sigue funcionando? ¿No me gusta el otro enfoque?
MTZ
1
@AbhijitSrivastava ¡Gracias! Mi error, pasé un blob ( thumbnail) en lugar de una URL
MTZ
1
No se recomienda llamar getBackgrounddentro de la vista, porque Angular tiene que llamar bypassSecurityTrustStylecada vez que se actualiza esa vista. Para probar eso, agregue console.log adentro getBackgroundy verá que se llama a la función en cada clic o evento de desplazamiento del usuario
Marcin
9

Consulte esta práctica tubería para Angular2: Uso:

  1. en el SafePipecódigo, sustituir DomSanitizationServiceconDomSanitizer

  2. proporcione el SafePipesi suNgModule

  3. <div [style.background-image]="'url(' + your_property + ')' | safe: 'style'"></div>

SimoneMSR
fuente
8

Según los documentos en https://angular.io/api/platform-browser/DomSanitizer , la forma correcta de hacer esto parece ser usar sanitize. Al menos en Angular 7 (no sé si esto cambió desde antes). Esto funcionó para mí:

import { Component, OnInit, Input, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

constructor(
    private sanitizer: DomSanitizer
) { }

this.sanitizer.sanitize(SecurityContext.STYLE, 'url(' + this.image + ')');

Con respecto a SecurityContext, consulte https://angular.io/api/core/SecurityContext . Básicamente es solo esta enumeración:

enum SecurityContext {
  NONE: 0
  HTML: 1
  STYLE: 2
  SCRIPT: 3
  URL: 4
  RESOURCE_URL: 5
}
Dovev Hefetz
fuente
1
Esta es la respuesta más actualizada. También se puede acortar:this.sanitizer.bypassSecurityTrustStyle(`url('${this.image} ')`);
Zahema
@Zahema No creo que eso sea equivalente a la respuesta proporcionada. bypassSecurityTrustStyleignora la seguridad mientras sanitize(SecurityContext.STYLE, style)refuerza la seguridad. Recomendaría usar sanitizecon el apropiado SecurityContext.
Oscar
@Zahema bypassSecurityTrustStyledevuelve un Objeto al que no se puede acceder (al menos no pude hacerlo) en [ngStyle]. sanitize(SecurityContext.STYLE, style)en su lugar, devuelve una cadena simple.
Alexander Fink
@Oscar Estoy de acuerdo, pero por alguna razón no siempre funciona como se esperaba en todos los escenarios. bypassSecurityTrustStylees básicamente la fuerza bruta.
Zahema
6

Tuve el mismo problema al agregar una URL dinámica en la etiqueta de imagen en Angular 7. Busqué mucho y encontré esta solución.

Primero, escriba el código siguiente en el archivo del componente.

constructor(private sanitizer: DomSanitizer) {}
public getSantizeUrl(url : string) {
    return this.sanitizer.bypassSecurityTrustUrl(url);
}

Ahora, en su etiqueta de imagen html, puede escribir así.

<img class="image-holder" [src]=getSantizeUrl(item.imageUrl) />

Puede escribir según su requisito en lugar de item.imageUrl

Obtuve una referencia de este sitio. URL dinámicas . Espero que esta solución te ayude :)

Arjun
fuente
funciona para imágenes, pero la pregunta era sobre URL en estilo, usando como imagen de fondo, que esta respuesta no está relacionada
Amirreza
3

Hay un problema abierto para imprimir esta advertencia solo si realmente hubo algo desinfectado: https://github.com/angular/angular/pull/10272

No leí en detalle cuando se imprimió esta advertencia cuando no se desinfectó nada.

Günter Zöchbauer
fuente
3
Para aquellos que puedan venir aquí: ese problema ha sido resuelto. Solo imprime la advertencia SI desinfectó HTML y no todo el tiempo.
flamusdiu
Quería saber si es una práctica incorrecta hacerlo. ¿Debería intentar no recibir esta advertencia?
Amrit
Debe tener mucho cuidado al aplicar esto al contenido proporcionado por el usuario (como el texto de un campo de entrada o el contenido del usuario cargado desde una base de datos u otras fuentes que no controla. De esta manera, le dice a Angular que el contenido intrínsecamente inseguro debe tratarse como Trustworty. Está totalmente bien usarlo para contenido estático que controlas, como constantes, variables de entorno pasadas en el momento de la compilación, valores calculados solo a partir de esos valores seguros.
Günter Zöchbauer
1

Para cualquiera que ya esté haciendo lo que la advertencia sugiere que haga, antes de la actualización a Angular 5, tuve que asignar mis SafeStyletipos stringantes de usarlos en las plantillas. Después de Angular 5, este ya no es el caso. Tuve que cambiar mis modelos para tener un en image: SafeStylelugar de image: string. Ya estaba usando el [style.background-image]enlace de propiedad y eludiendo la seguridad en toda la URL.

Espero que esto ayude a alguien.

Jake Smith
fuente
0

Dado que Angular no es una biblioteca de desinfección dedicada, es demasiado entusiasta con el contenido sospechoso para no correr riesgos. Puede delegar la desinfección a una biblioteca dedicada, por ejemplo, DOMPurify. Aquí hay una biblioteca contenedora que hice para usar fácilmente DOMPurify con Angular.

https://github.com/TinkoffCreditSystems/ng-dompurify

Tiene una tubería para desinfectar HTML declarativamente:

<div [innerHtml]="value | dompurify"></div>

Una cosa a tener en cuenta es que DOMPurify es excelente para desinfectar HTML / SVG, pero no CSS. Entonces puede proporcionar el desinfectante CSS de Angular para manejar CSS:

import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}

Es interno, ɵprefijo hense , pero así es como el equipo de Angular lo usa también en sus propios paquetes.

waterplea
fuente
-1

En mi caso, obtuve la URL de la imagen antes de llegar al componente de visualización y quiero usarla como imagen de fondo, así que para usar esa URL tengo que decirle a Angular que es segura y que se puede usar.

En archivo .ts

userImage: SafeStyle;
ngOnInit(){
    this.userImage = this.sanitizer.bypassSecurityTrustStyle('url(' + sessionStorage.getItem("IMAGE") + ')');
}

En archivo .html

<div mat-card-avatar class="nav-header-image" [style.background-image]="userImage"></div>
SANTOSH
fuente
Edite su respuesta para explicarla y observe por qué es una mejor respuesta que cualquiera de las existentes.
Dragon Thoughts