AVERTISSEMENT: désinfection de l'URL de valeur de style non sécurisé

107

Je souhaite définir l'image d'arrière-plan d'une DIV dans un modèle de composant dans mon application Angular 2. Cependant, je continue à recevoir l'avertissement suivant dans ma console et je n'obtiens pas l'effet souhaité ... Je ne sais pas si l'image d'arrière-plan CSS dynamique est bloquée en raison de restrictions de sécurité dans Angular2 ou si mon modèle HTML est cassé.

C'est l'avertissement que je vois dans ma console (j'ai changé mon URL d'img en /img/path/is/correct.png:

AVERTISSEMENT: nettoyage de l'url de la valeur de style unsafe (SafeValue doit utiliser [property] = binding: /img/path/is/correct.png (voir http://g.co/ng/security#xss )) (voir http: // g.co/ng/security#xss ).

Le fait est que je désinfecte ce qui est injecté dans mon modèle en utilisant le DomSanitizationServicedans Angular2. Voici mon HTML que j'ai dans mon modèle:

<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>

Voici le composant ...

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;
                }

            }
        }
    }
}

Veuillez noter que lorsque je viens de me connecter au modèle en utilisant [src] = "image", par exemple:

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

et a imageété adopté en utilisant bypassSecurityTrustUrltout semblait bien fonctionner ... quelqu'un peut-il voir ce que je fais mal?

Mark Sandman
la source
Avez-vous obtenu une solution à votre question. J'ai exactement le même problème et j'essaie toujours de trouver une solution. Merci d'avance!
SK.

Réponses:

112

Vous devez envelopper l'ensemble de l' urlinstruction dans le bypassSecurityTrustStyle:

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

Et avoir

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

Sinon, il n'est pas considéré comme une propriété de style valide

Poul Kruijt
la source
1
PierreDuc, des mots de sagesse pour quand l'image de fond est contournée comme ci-dessus, mais alors Angular2 l'ignore silencieusement? Je peux poster une nouvelle question, mais je pense que c'est assez pertinent pour votre réponse.
David Pfeffer
@DavidPfeffer Il est difficile de juger où les choses vont mal sans voir de code :) J'utilise ce code dans le dernier angular2 et il fonctionne toujours ..
Poul Kruijt
1
Je l'ai compris. Après avoir contourné le nettoyage, si la valeur n'est pas valide, Angular2 l'ignore silencieusement.
David Pfeffer
Vous devriez ngStyle et cela fonctionnera sans jouer avec la désinfection.
yglodt
A travaillé pour moi dans Angular8. Je pense que la désinfection est la meilleure ... elle existe pour une raison. @yglodt.
Sean Halls le
67

Utilisez ceci, <div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>cela a résolu le problème pour moi.

iRedia Ebikade
la source
Sûr et simple.
Kenmore
Merci pour vos aimables paroles @Kenmore. Je suis content de pouvoir vous aider. À votre santé.
iRedia Ebikade
@ Sammy-RogersGeek puis-je écrire le même code dans la balise Image?
Arjun
Vous sauvez ma journée!
VAdaihiep
Éloquent. Je vous remercie.
Mindsect Team
52

Si l'image d'arrière-plan avec gradient linéaire ( *ngFor)

Vue:

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

Classe:

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
la source
1
vous avez sauvé ma journée
Thamaraiselvam
1
Fonctionne parfaitement :))
Abhijit Srivastava
@AbhijitSrivastava J'ai écrit l' thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url ($ {miniature}) )et [style.backgroundImage]="thumbnailMediumIcon". Quelle version angulaire avez-vous utilisée? J'ai aussi essayé l'image d'arrière-plan. Cela fonctionne-t-il toujours? Je n'aime pas l'autre approche?
MTZ
1
@AbhijitSrivastava Merci! Mon erreur, j'ai passé un blob ( thumbnail) au lieu d'une URL
MTZ
1
Il n'est pas recommandé d'appeler getBackgroundà l'intérieur de la vue, car Angular doit appeler bypassSecurityTrustStylechaque fois que cette vue est actualisée. Pour tester cela, ajoutez console.log à l'intérieur getBackgroundet vous verrez que la fonction est appelée à chaque clic ou événement de défilement utilisateur
Marcin
9

Vérifiez ce tuyau pratique pour Angular2: Utilisation:

  1. dans le SafePipecode, remplacez DomSanitizationServiceparDomSanitizer

  2. fournir le SafePipesi votreNgModule

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

SimoneMSR
la source
8

Sur la base des documents disponibles sur https://angular.io/api/platform-browser/DomSanitizer , la bonne façon de procéder semble être d'utiliser sanitize. Au moins dans Angular 7 (je ne sais pas si cela a changé par rapport à avant). Cela a fonctionné pour moi:

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 + ')');

Re SecurityContext, voir https://angular.io/api/core/SecurityContext . Fondamentalement, c'est juste cette énumération:

enum SecurityContext {
  NONE: 0
  HTML: 1
  STYLE: 2
  SCRIPT: 3
  URL: 4
  RESOURCE_URL: 5
}
Dovev Hefetz
la source
1
Ceci est la réponse la plus récente. Il peut aussi être court-circuité:this.sanitizer.bypassSecurityTrustStyle(`url('${this.image} ')`);
Zahema
@Zahema Je ne pense pas que cela équivaut à la réponse fournie. bypassSecurityTrustStyleignore la sécurité tout en sanitize(SecurityContext.STYLE, style)renforçant la sécurité. Je recommanderais d'utiliser sanitizeavec le approprié SecurityContext.
Oscar le
@Zahema bypassSecurityTrustStylerenvoie un objet auquel il est impossible d'accéder (du moins je ne pouvais pas le faire) dans [ngStyle]. sanitize(SecurityContext.STYLE, style)renvoie à la place une chaîne simple.
Alexander Fink le
@Oscar Je suis d'accord mais pour une raison quelconque, cela ne fonctionne pas toujours comme prévu dans tous les scénarios. bypassSecurityTrustStyleest fondamentalement le forçant brutalement.
Zahema le
6

J'ai eu le même problème en ajoutant une URL dynamique dans la balise Image dans Angular 7. J'ai beaucoup cherché et trouvé cette solution.

Tout d'abord, écrivez le code ci-dessous dans le fichier du composant.

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

Maintenant, dans votre balise d'image html, vous pouvez écrire comme ça.

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

Vous pouvez écrire selon vos besoins au lieu de item.imageUrl

J'ai eu une référence sur ce site. URL dynamiques . J'espère que cette solution vous aidera :)

Arjun
la source
cela fonctionne pour les images, mais la question portait sur l'URL dans le style, en utilisant comme image de fond, ce qui n'est pas lié à cette réponse
Amirreza
3

Il existe un problème ouvert pour n'imprimer cet avertissement que s'il y avait réellement quelque chose de désinfecté: https://github.com/angular/angular/pull/10272

Je n'ai pas lu en détail quand cet avertissement est imprimé alors que rien n'a été désinfecté.

Günter Zöchbauer
la source
3
Pour ceux qui pourraient venir ici: ce problème a été résolu. Il n'imprime l'avertissement que SI il a nettoyé le HTML et pas tout le temps.
flamusdiu
Je voulais savoir si c'était une mauvaise pratique de le faire? Dois-je essayer de ne pas recevoir cet avertissement?
Amrit
Vous devez être très prudent lorsque vous appliquez cela au contenu fourni par l'utilisateur (comme le texte d'un champ d'entrée ou le contenu utilisateur chargé à partir d'une base de données ou d'autres sources que vous ne contrôlez pas. De cette façon, vous indiquez à Angular que le contenu intrinsèquement dangereux doit être traité comme trustworty. C'est tout à fait correct de l'utiliser pour du contenu statique que vous contrôlez, comme des constantes, des variables d'environnement transmises au moment de la construction, des valeurs calculées uniquement à partir de ces valeurs sûres.
Günter Zöchbauer
1

Pour tous ceux qui font déjà ce que l'avertissement vous suggère de faire, avant la mise à niveau vers Angular 5, je devais mapper mes SafeStyletypes stringavant de les utiliser dans les modèles. Après Angular 5, ce n'est plus le cas. J'ai dû changer mes modèles pour avoir une image: SafeStyleplace de image: string. J'utilisais déjà la [style.background-image]propriété binding et contournais la sécurité sur toute l'url.

J'espère que cela aide quelqu'un.

Jake Smith
la source
0

Comme Angular n'est pas une bibliothèque de désinfection dédiée, il est trop zélé envers les contenus suspects de ne prendre aucun risque. Vous pouvez déléguer le nettoyage à une bibliothèque dédiée, par exemple - DOMPurify. Voici une bibliothèque de wrapper que j'ai créée pour utiliser facilement DOMPurify avec Angular.

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

Il a un tube pour nettoyer le HTML de manière déclarative:

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

Une chose à garder à l'esprit est que DOMPurify est idéal pour nettoyer HTML / SVG, mais pas CSS. Vous pouvez donc fournir le désinfectant CSS d'Angular pour gérer les CSS:

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

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

C'est interne - ɵpréfixe hense , mais c'est ainsi que l'équipe Angular l'utilise également dans ses propres packages.

waterplea
la source
-1

Dans mon cas, j'ai obtenu l'URL de l'image avant d'accéder au composant d'affichage et je souhaite l'utiliser comme image d'arrière-plan.Pour utiliser cette URL, je dois dire à Angular qu'elle est sûre et peut être utilisée.

Dans le fichier .ts

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

Dans un fichier .html

<div mat-card-avatar class="nav-header-image" [style.background-image]="userImage"></div>
SANTOSH
la source
Veuillez modifier votre réponse pour l'expliquer et noter pourquoi c'est une meilleure réponse que n'importe laquelle des réponses existantes.
Dragonthoughts