Application security is like the walls of Himeji Castle 城 - multi-layered defense against enemies. Himeji Castle survived for centuries thanks to its well-designed fortifications - your application needs the same level of protection!
| Threat | Description | Angular Protection | |--------|-------------|-------------------| | XSS | Injection of malicious scripts | Automatic sanitization | | CSRF | Cross-site request forgery | HttpXsrfModule | | Injection | Code injection | Parameterized queries | | Clickjacking | Hidden iframes | X-Frame-Options |
Angular automatically sanitizes all values in templates:
1@Component({
2 template: \`
3 <!-- Safe - Angular escapes HTML -->
4 <div>{{ userInput }}</div>
5
6 <!-- Safe - Angular sanitizes URL -->
7 <a [href]="userUrl">Link</a>
8
9 <!-- Safe - Angular sanitizes styles -->
10 <div [style.background]="userBackground">...</div>
11 \`
12})
13export class SafeComponent {
14 // Even if userInput = '<script>alert("XSS")</script>'
15 // Angular will display the text, not execute the script
16 userInput = '<script>alert("XSS")</script>';
17}Sometimes you need to display trusted HTML (e.g., from a WYSIWYG editor):
1import { DomSanitizer, SafeHtml, SafeUrl } from '@angular/platform-browser';
2
3@Component({
4 template: \`
5 <!-- Using pipe or binding -->
6 <div [innerHTML]="trustedHtml"></div>
7 <iframe [src]="trustedUrl"></iframe>
8 \`
9})
10export class TrustedContentComponent {
11 private sanitizer = inject(DomSanitizer);
12
13 trustedHtml: SafeHtml;
14 trustedUrl: SafeUrl;
15
16 constructor() {
17 // IMPORTANT: Use only for TRUSTED sources!
18 this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml(
19 '<b>Trusted HTML</b>'
20 );
21
22 this.trustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
23 'https://trusted-site.com/embed'
24 );
25 }
26}
27
28// Reusable pipe
29@Pipe({ name: 'safeHtml', standalone: true })
30export class SafeHtmlPipe implements PipeTransform {
31 private sanitizer = inject(DomSanitizer);
32
33 transform(value: string): SafeHtml {
34 return this.sanitizer.bypassSecurityTrustHtml(value);
35 }
36}CSP is an additional layer of defense - like the outer walls of the castle:
1<!-- index.html -->
2<meta http-equiv="Content-Security-Policy" content="
3 default-src 'self';
4 script-src 'self' 'unsafe-inline';
5 style-src 'self' 'unsafe-inline';
6 img-src 'self' data: https:;
7 font-src 'self';
8 connect-src 'self' https://api.example.com;
9">1// app.config.ts
2import { provideHttpClient, withXsrfConfiguration } from '@angular/common/http';
3
4export const appConfig: ApplicationConfig = {
5 providers: [
6 provideHttpClient(
7 withXsrfConfiguration({
8 cookieName: 'XSRF-TOKEN',
9 headerName: 'X-XSRF-TOKEN'
10 })
11 )
12 ]
13};