This episode covers web security practices: preventing XSS, CSRF, and injection, applying content security policy and secure headers, sanitizing HTML and handling URLs safely, and client-side security best practices.

Authentication is only one layer of security. The other side, just as important, is how the application processes user input, renders content, and talks to the server. This is where XSS, CSRF, and injection attacks often happen.
Episode 13 covers preventing XSS, CSRF, and injection, content security policy and secure headers, HTML sanitization and safe URLs, and client-side security best practices. Angular already provides a lot of protection by default — our job is not to dismantle it without reason.
Cross-Site Scripting (XSS) happens when malicious JavaScript makes its way into a page and executes in the victim's browser. Common sources: user input displayed without sanitization, or HTML attributes filled with untrusted data.
By default, Angular sanitizes all values rendered through interpolation and binding. Consider this example:
@Component({
selector: 'app-komentar',
standalone: true,
template: `<p>{{ komentar }}</p>`,
})
export class KomentarComponent {
komentar = '<script>alert("xss")</script>';
}Even though komentar contains <script>, Angular will display it as plain text instead of executing it. This is the default protection you must preserve: always use interpolation and binding, and never inject raw HTML into the DOM.
CSRF tricks the victim's browser into sending malicious requests to a trusted site. Prevention: use a CSRF token, verify a custom header like X-Requested-With, and use httpOnly cookies with the SameSite attribute. Injection — SQL injection, command injection — happens server-side; on the frontend, always treat data from the server as untrusted until validated.
Content Security Policy restricts what resources a page may load. A strict policy blocks inline scripts and disallowed external sources:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'The policy above only allows scripts from your own domain and inline styles. CSP can be set via a server header or a meta tag. Angular builds with hashing are safe under policies like this.
Besides CSP, make sure the server sends: Strict-Transport-Security to force HTTPS, X-Content-Type-Options: nosniff, Referrer-Policy, and X-Frame-Options to prevent clickjacking. These headers can be added in a web server like nginx, or in hosting platforms like Vercel and Netlify.
Sometimes an application genuinely must display HTML from the server. Don't disable Angular's sanitization carelessly. If you must, use DomSanitizer and review very carefully:
import { Component, inject } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
selector: 'app-konten',
standalone: true,
template: `<div [innerHTML]="htmlAman"></div>`,
})
export class KontenComponent {
private readonly sanitizer = inject(DomSanitizer);
htmlAman: SafeHtml = '';
}SafeHtml tells Angular the developer has explicitly declared the value safe. This means you take over the sanitization responsibility — use it only when the content truly comes from a trusted source.
URLs can also be dangerous — for example javascript: as a scheme. Angular blocks dangerous URLs in href and src bindings. To open a link from user data, use bypassSecurityTrustUrl only after validating the scheme:
function urlAman(raw: string): SafeUrl | null {
if (!/^https?:\/\//i.test(raw)) {
return null;
}
return sanitizer.bypassSecurityTrustUrl(raw);
}The ^https?:\/\// regex ensures only URLs with the http or https scheme are accepted. All other schemes are rejected — this pattern prevents dangerous javascript: URLs.
innerHTML manipulation.SameSite and httpOnly.Perform security audits periodically: run npm audit for dependencies, use automated scanners for security headers, and review code that uses bypassSecurityTrust*. Security isn't a one-time task — it's maintained every day.
Key takeaways:
SameSite cookies.DomSanitizer is only for trusted content, with strict review.javascript: links never get through.In the next episode, episode 14, we'll cover API communication and caching — using HTTP interceptors for centralized error handling, caching strategies for API responses, state transfer and server-side rendering cache, and optimizing network request performance.