AVISO: higienização de url de valor de estilo inseguro

107

Quero definir a imagem de plano de fundo de um DIV em um modelo de componente em meu aplicativo Angular 2. No entanto, continuo recebendo o seguinte aviso em meu console e não obtenho o efeito desejado ... Não tenho certeza se a imagem de plano de fundo do CSS dinâmico está sendo bloqueada devido a restrições de segurança no Angular2 ou se meu modelo HTML está quebrado.

Este é o aviso que vejo em meu console (mudei meu url img para /img/path/is/correct.png:

AVISO: higienizando url de valor de estilo inseguro (SafeValue deve usar [propriedade] = binding: /img/path/is/correct.png (consulte http://g.co/ng/security#xss )) (consulte http: // g.co/ng/security#xss ).

O que acontece é que eu limpo o que é injetado no meu modelo usando o DomSanitizationServiceAngular2. Aqui está o meu HTML que tenho em meu modelo:

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

Aqui está o 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;
                }

            }
        }
    }
}

Observe que quando acabei de vincular ao modelo usando [src] = "imagem", por exemplo:

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

e imagepassou usando bypassSecurityTrustUrltudo parecia funcionar bem ... alguem pode ver o que estou fazendo de errado?

Mark Sandman
fonte
Você conseguiu solução para sua pergunta. Tenho exatamente o mesmo problema e ainda estou tentando encontrar uma solução. Desde já, obrigado!
SK.

Respostas:

112

Você tem que envolver toda a urlinstrução em bypassSecurityTrustStyle:

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

E tem

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

Caso contrário, não é visto como uma propriedade de estilo válida

Poul Kruijt
fonte
1
PierreDuc, alguma palavra de sabedoria para quando a imagem de fundo É contornada como acima, mas então o Angular2 silenciosamente a ignora? Posso postar uma nova pergunta, mas acho que é bastante pertinente à sua resposta.
David Pfeffer
@DavidPfeffer É difícil julgar onde as coisas dão errado sem ver nenhum código :) Eu uso este código no angular2 mais recente e ainda está funcionando ..
Poul Kruijt
1
Eu descobri. Depois de ignorar a higienização, se o valor for inválido, o Angular2 o ignora silenciosamente.
David Pfeffer
Você deve usar o ngStyle e ele funcionará sem mexer na higienização.
yglodt de
Trabalhou para mim no Angular8. Acho que higienizar é melhor ... existe por uma razão. @yglodt.
Sean Halls
67

Use isso para <div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>resolver o problema para mim.

iRedia Ebikade
fonte
Seguro e simples.
Kenmore
Obrigado por suas amáveis ​​palavras @Kenmore. Estou feliz por poder ajudar. Felicidades.
iRedia Ebikade
@ Sammy-RogersGeek posso escrever o mesmo código na tag de imagem?
Arjun
Você salva meu dia!
VAdaihiep
Eloquente. Obrigado.
Equipe Mindsect
52

Se a imagem de fundo com gradiente linear ( *ngFor)

Visão:

<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
fonte
1
você salvou meu dia
Thamaraiselvam
1
Funciona perfeitamente :))
Abhijit Srivastava
@AbhijitSrivastava escrevi thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url ($ {thumbnail}) )e [style.backgroundImage]="thumbnailMediumIcon". Qual versão Angular você usou? Eu também tentei background-image. Ainda está funcionando? Eu não gosto da outra abordagem?
MTZ
1
@AbhijitSrivastava Obrigado! Erro meu, passei um blob ( thumbnail) em vez de um URL
MTZ
1
Não é recomendado chamar getBackgrounddentro da vista, porque o Angular tem que chamar bypassSecurityTrustStylecada vez que a vista é atualizada. Para testar isso, adicione console.log dentro getBackgrounde você verá que a função é chamada a cada clique ou evento de rolagem do usuário
Marcin
9

Verifique este tubo útil para Angular2: Uso:

  1. no SafePipecódigo, substitua DomSanitizationServiceporDomSanitizer

  2. forneça SafePipese o seuNgModule

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

SimoneMSR
fonte
8

Com base na documentação em https://angular.io/api/platform-browser/DomSanitizer , a maneira certa de fazer isso parece ser usando sanitize. Pelo menos no Angular 7 (não sei se mudou desde antes). Isso funcionou para mim:

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

Sobre SecurityContext, consulte https://angular.io/api/core/SecurityContext . Basicamente, é apenas este enum:

enum SecurityContext {
  NONE: 0
  HTML: 1
  STYLE: 2
  SCRIPT: 3
  URL: 4
  RESOURCE_URL: 5
}
Dovev Hefetz
fonte
1
Esta é a resposta mais atualizada. Também pode ser abreviado:this.sanitizer.bypassSecurityTrustStyle(`url('${this.image} ')`);
Zahema
@Zahema Não creio que seja equivalente à resposta fornecida. bypassSecurityTrustStyleignora a segurança enquanto sanitize(SecurityContext.STYLE, style)reforça a segurança. Eu recomendaria usar sanitizecom o apropriado SecurityContext.
Oscar
@Zahema bypassSecurityTrustStyleretorna um objeto que não pode ser acessado (pelo menos eu não poderia fazer isso) em [ngStyle]. sanitize(SecurityContext.STYLE, style)em vez disso, retorna uma string simples.
Alexander Fink
@Oscar Eu concordo, mas por alguma razão nem sempre funciona como esperado em todos os cenários. bypassSecurityTrustStyleé basicamente força bruta.
Zahema
6

Eu tive o mesmo problema ao adicionar url dinâmico na tag de imagem no Angular 7. Eu pesquisei muito e encontrei essa solução.

Primeiro, escreva o código abaixo no arquivo do componente.

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

Agora, em sua tag de imagem html, você pode escrever assim.

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

Você pode escrever conforme sua necessidade em vez de item.imageUrl

Eu tenho uma referência deste site. urls dinâmicas . Espero que esta solução ajude você :)

Arjun
fonte
funciona para imagens, mas a questão era sobre o estilo de URL, usando como imagem de fundo, cuja resposta não está relacionada
Amirreza
3

Há um problema em aberto para imprimir este aviso apenas se realmente houver algo higienizado: https://github.com/angular/angular/pull/10272

Não li em detalhes quando este aviso é impresso quando nada foi higienizado.

Günter Zöchbauer
fonte
3
Para aqueles que podem vir aqui: esse problema foi resolvido. Ele só imprime o aviso SE ele higienizou o HTML e não o tempo todo.
flamusdiu
Eu queria saber se é uma prática errada fazer isso? Devo tentar não receber este aviso?
Amrit
Você deve ter muito cuidado ao aplicar isso ao conteúdo fornecido pelo usuário (como texto de um campo de entrada ou conteúdo do usuário carregado de um banco de dados ou outras fontes que você não controla. Desta forma, você diz ao Angular que conteúdo inerentemente inseguro deve ser tratado como trustworty. Não há problema em usá-lo para conteúdo estático que você controla, como constantes, variáveis ​​de ambiente passadas no momento da criação, valores calculados apenas a partir desses valores seguros.
Günter Zöchbauer
1

Para quem já está fazendo o que o aviso sugere que você faça, antes da atualização para o Angular 5, tive que mapear meus SafeStyletipos stringantes de usá-los nos modelos. Depois do Angular 5, esse não é mais o caso. Tive que mudar meus modelos para ter um em image: SafeStylevez de image: string. Eu já estava usando a [style.background-image]vinculação de propriedade e contornando a segurança em todo o url.

Espero que isso ajude alguém.

Jake Smith
fonte
0

Como o Angular não é uma biblioteca de higienização dedicada, é muito zeloso com conteúdo suspeito para não correr riscos. Você pode delegar a higienização a uma biblioteca dedicada, por exemplo - DOMPurify. Aqui está uma biblioteca de wrapper que criei para usar facilmente DOMPurify com Angular.

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

Ele tem um tubo para higienizar declarativamente o HTML:

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

Uma coisa a se ter em mente é que o DOMPurify é ótimo para limpar HTML / SVG, mas não CSS. Portanto, você pode fornecer o sanitizer CSS da Angular para lidar com CSS:

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

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

É um ɵprefixo interno - hense , mas é assim que a equipe Angular também o usa em seus próprios pacotes.

plumagem
fonte
-1

No meu caso, obtive o URL da imagem antes de chegar ao componente de exibição e quero usá-lo como imagem de plano de fundo, então, para usar esse URL, preciso dizer ao Angular que é seguro e pode ser usado.

No arquivo .ts

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

Em arquivo .html

<div mat-card-avatar class="nav-header-image" [style.background-image]="userImage"></div>
SANTOSH
fonte
Edite sua resposta para explicá-la e observe por que é uma resposta melhor do que qualquer uma das existentes.
Dragonthoughts