Dados apresentados e código de template
Angular trata valores recebidos como não confiáveis por omissão, mas trata templates como código confiável da aplicação. A interpolação do exemplo apresenta a string como texto; a tag strong permanece texto nessa primeira vista. Isto é diferente de concatenar entrada do utilizador com sintaxe Angular e compilar o resultado.
Nessa alteração, o conteúdo já atravessou a fronteira de dados para código e a sanitização de uma binding não corrige a causa. Mantém templates sob controlo da aplicação e fornece conteúdo variável através de bindings adequadas.
O contexto determina a proteção
Uma string não é segura para todos os destinos só porque foi aceite num deles. HTML, Style, URL e Resource URL têm contratos distintos. A binding innerHTML interpreta HTML e Angular sanitiza valores não confiáveis nesse contexto.
Um URL usado para navegação difere de um endereço que carrega conteúdo executável, como iframe src. Não é possível transformar qualquer Resource URL arbitrário em seguro apenas retirando alguns caracteres. A decisão deve considerar a origem permitida, o conteúdo carregado e o contexto exato.
Uma aprovação para HTML não constitui aprovação para executar um recurso.
Sanitizar e declarar confiança são operações diferentes
DomSanitizer.sanitize com SecurityContext.HTML e uma string normal aplica sanitização ao conteúdo. Já bypassSecurityTrustHtml declara o valor confiável e contorna a proteção desse contexto. Essa declaração exige uma análise da origem e construção do valor; não é uma correção automática para uma mensagem de erro.
A API sanitize também pode desembrulhar um SafeValue já marcado, pelo que a confiança atribuída anteriormente continua relevante. Para outros contextos, passar uma string normal a essa API explícita pode produzir erro, conforme o contrato documentado. Não generalizes a semântica de HTML para todos os destinos.
APIs DOM e integrações externas
ElementRef permite aceder a um elemento, mas essa referência não sanitiza automaticamente todas as operações que se fazem sobre ele. Escrever diretamente em innerHTML ou entregar uma string a uma biblioteca que manipula DOM pode evitar o caminho de uma binding Angular.
Prefere o contrato de template quando adequado; quando a integração exige acesso direto, define a sanitização compatível com o destino e revê transformações posteriores. Alterar o tipo para any ou usar uma assertion não modifica o conteúdo nem o modo como o browser o interpreta.
Autorização pertence também ao servidor
Um guard pode impedir a navegação normal para uma página ou orientar o utilizador para outra. Não impede que o código cliente seja alterado ou que um pedido seja enviado diretamente à API. O servidor deve verificar a identidade, a operação e o recurso pedido.
Esconder um botão ou desativar um campo melhora o fluxo da interface, mas não estabelece essa permissão. Num cenário de diagnóstico, uma resposta aceite para uma operação sem autorização deve levar à verificação do backend, mesmo que os guards e as classes visuais pareçam corretos.
XSRF exige os dois lados do contrato
A proteção XSRF de HttpClient implementa a parte cliente de um esquema de token. Por omissão, lê XSRF-TOKEN e usa X-XSRF-TOKEN nos pedidos mutantes elegíveis para URLs relativos ou da mesma origem; GET e HEAD não recebem esse tratamento. O backend deve emitir o token e verificar pedidos segundo a política acordada.
Sem isso, a presença de HttpClient não completa a proteção. Quando os nomes diferem, withXsrfConfiguration permite alinhar cookieName e headerName. Desativar o mecanismo não resolve a ausência de uma verificação no servidor.
CSP, Trusted Types e revisão de entrega
CSP e Trusted Types acrescentam proteção no nível do browser e DOM, complementando os contratos anteriores. Numa política CSP baseada em nonce, o servidor gera um valor aleatório por resposta e o valor fornecido a Angular por ngCspNonce ou CSP_NONCE deve corresponder ao header dessa resposta.
Não copies um nonce fixo de um exemplo para todas as respostas. Usa AOT no processo de entrega conforme a orientação Angular e evita compilar templates construídos a partir de dados externos. Estas medidas não substituem autorização nem uma revisão das APIs de bypass existentes na aplicação.
// Reading example: two Angular rendering contexts; no storage or API.
import {Component, signal} from '@angular/core';
@Component({
selector: 'comment-preview', standalone: true,
template: `<label>Comment
<textarea #entry [value]="comment()" (input)="comment.set(entry.value)"></textarea>
</label>
<h2>Text preview</h2><p>{{ comment() }}</p>
<h2>HTML binding preview</h2><div [innerHTML]="comment()"></div>`,
})
export class CommentPreview {
readonly comment = signal('A <strong>draft</strong> note');
}A interpolação apresenta os caracteres da string como texto. A binding innerHTML pede interpretação como HTML e usa a proteção Angular desse contexto. O exemplo não chama bypassSecurityTrustHtml nem escreve diretamente em nativeElement.
A existência desta pré-visualização não define uma política completa de publicação de comentários, permissões, links externos ou conteúdo de terceiros.
Armadilhas comuns
Tratar bypass como sanitização; considerar todo o conteúdo de uma API confiável; compilar dados do utilizador como template; confiar só num guard para proteger a API; ativar o cliente XSRF sem backend; reutilizar um nonce CSP fixo.
Tópicos relacionados: HTTP, streams e aceitação de respostas · Routing, estado e decisões de navegação · Renderização, hidratação e evidência de entrega
A segurança depende da fronteira concreta: dados para DOM, dados para template, cliente para servidor e código para política de execução. Mantém dados não confiáveis como dados, usa proteção adequada ao destino e exige evidência própria para autorização e aceitação remota.
Referência: Untrusted data and trusted templates · Angular 22; standalone components