Rendering a raw HTML string in an Angular template — content from a CMS, a rich-text field — needs the innerHTML binding rather than Angular's default text interpolation, and Angular automatically sanitizes it by default as an XSS protection you generally shouldn't bypass without good reason.
Basic innerHTML binding
@Component({
template: ``
})
export class ArticleComponent {
htmlContent = 'This is formatted content.
';
}
Angular automatically strips potentially dangerous content (like a tag or an onclick attribute) from an innerHTML binding by default — this sanitization happens transparently, without needing to opt into it.
What gets stripped by Angular's default sanitization
htmlContent = 'Click me
';
// renders as: Click me
— the onclick attribute and script tag are both removed
Bypassing sanitization with DomSanitizer, when content is genuinely trusted
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
export class ArticleComponent {
trustedHtml: SafeHtml;
constructor(private sanitizer: DomSanitizer) {
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml(this.getTrustedContent());
}
}
bypassSecurityTrustHtml() is an explicit, deliberate opt-out of Angular's default protection — reaching for it should be limited specifically to content from a genuinely trusted source (your own backend's sanitized CMS output, never raw, unsanitized user input) given what it actually disables.
The risk of bypassing sanitization on untrusted content
Calling bypassSecurityTrustHtml() on content that could contain user-supplied HTML reopens exactly the XSS vulnerability Angular's default sanitization exists to prevent — this method name is deliberately explicit about what it does specifically to make this risk clear at the call site to anyone reading the code later.
Sanitizing user-generated HTML server-side instead
For genuinely user-generated rich content, sanitizing it server-side (using a library like HTMLPurifier on the Laravel API side, following the approach covered for Blade elsewhere on this site) before it ever reaches the Angular front end is generally the more robust approach — by the time it reaches Angular, it's already safe, and Angular's own default sanitization then serves as a reasonable second layer of defense rather than the only one.
Alternative: Markdown instead of raw HTML
Following the same principle covered for Laravel Blade elsewhere on this site, accepting Markdown from users and rendering it through a Markdown-to-HTML library (many of which have Angular-specific wrappers) avoids the raw-HTML sanitization question largely by construction, since Markdown's syntax has no way to embed executable script content in the first place.