> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Best Practices

> Comprehensive guide to Angular security including XSS prevention, sanitization, trusted values, and Content Security Policy

# Security Best Practices

Angular has built-in protections against common web application vulnerabilities and attacks such as cross-site scripting (XSS). This guide covers Angular's security features and best practices to keep your applications secure.

<Warning>
  This guide focuses on Angular's built-in security features. It does not cover application-level security such as authentication, authorization, or server-side security.
</Warning>

## General Security Guidelines

<CardGroup cols={3}>
  <Card title="Keep Angular Updated" icon="arrow-up">
    Regular updates include security fixes. Check the [Angular changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) for security-related updates.
  </Card>

  <Card title="Don't Modify Angular" icon="lock">
    Private, customized versions fall behind and miss security fixes. Contribute improvements to the community instead.
  </Card>

  <Card title="Avoid Risky APIs" icon="triangle-exclamation">
    APIs marked "Security Risk" in documentation should be used with extreme caution.
  </Card>
</CardGroup>

## Preventing Cross-Site Scripting (XSS)

Cross-site scripting (XSS) enables attackers to inject malicious code into web pages. This is one of the most common attacks on the web.

### Angular's XSS Security Model

Angular treats all values as untrusted by default. When a value is inserted into the DOM from a template binding or interpolation, Angular sanitizes and escapes untrusted values.

<CodeGroup>
  ```typescript inner-html-binding.component.ts theme={null}
  import { Component } from '@angular/core';

  @Component({
    selector: 'app-inner-html-binding',
    template: `
      <!-- Interpolation - Always escaped -->
      <p>{{ htmlSnippet }}</p>
      
      <!-- innerHTML binding - Sanitized -->
      <div [innerHTML]="htmlSnippet"></div>
    `
  })
  export class InnerHtmlBindingComponent {
    // Angular automatically sanitizes dangerous content
    htmlSnippet = '<b>Bold text</b><script>alert("XSS")</script>';
    // Result: <b>Bold text</b> (script tag removed)
  }
  ```

  ```html Result theme={null}
  <!-- Interpolation output -->
  <p>&lt;b&gt;Bold text&lt;/b&gt;&lt;script&gt;alert("XSS")&lt;/script&gt;</p>

  <!-- innerHTML output (sanitized) -->
  <div><b>Bold text</b></div>
  <!-- The <script> tag is automatically removed -->
  ```
</CodeGroup>

### Security Contexts

Angular defines different security contexts, each with specific sanitization rules:

<Tabs>
  <Tab title="HTML">
    Used when interpreting a value as HTML, such as binding to `innerHTML`.

    ```typescript theme={null}
    @Component({
      template: `<div [innerHTML]="userContent"></div>`
    })
    export class MyComponent {
      userContent = '<b>Safe</b><script>unsafe()</script>';
      // Result: <b>Safe</b> (script removed)
    }
    ```
  </Tab>

  <Tab title="Style">
    Used when binding CSS into the `style` property.

    ```typescript theme={null}
    @Component({
      template: `<div [style.color]="userColor"></div>`
    })
    export class MyComponent {
      userColor = 'red';  // Safe
      // userColor = 'javascript:alert(1)';  // Would be sanitized
    }
    ```
  </Tab>

  <Tab title="URL">
    Used for URL properties like `<a href>`.

    ```typescript theme={null}
    @Component({
      template: `<a [href]="userUrl">Link</a>`
    })
    export class MyComponent {
      userUrl = 'https://example.com';  // Safe
      // userUrl = 'javascript:alert(1)';  // Sanitized to unsafe:javascript:alert(1)
    }
    ```
  </Tab>

  <Tab title="Resource URL">
    A URL loaded and executed as code, such as in `<script src>`.

    ```typescript theme={null}
    @Component({
      template: `<script [src]="scriptUrl"></script>`
    })
    export class MyComponent {
      // Resource URLs cannot be sanitized - must use DomSanitizer
      scriptUrl = this.sanitizer.bypassSecurityTrustResourceUrl('https://cdn.example.com/lib.js');
    }
    ```
  </Tab>
</Tabs>

## Sanitization and Trusted Values

### Direct DOM Manipulation

When using DOM APIs directly, you must manually sanitize untrusted values:

<CodeGroup>
  ```typescript Using DomSanitizer theme={null}
  import { Component, inject, ElementRef, viewChild, signal } from '@angular/core';
  import { DomSanitizer, SecurityContext } from '@angular/platform-browser';

  @Component({
    selector: 'app-manual-sanitization',
    template: `
      <div #container></div>
      <button (click)="addContent()">Add Content</button>
    `
  })
  export class ManualSanitizationComponent {
    private sanitizer = inject(DomSanitizer);
    private container = viewChild.required<ElementRef>('container');
    
    userContent = signal('<b>User content</b><script>alert("XSS")</script>');
    
    addContent() {
      const sanitized = this.sanitizer.sanitize(
        SecurityContext.HTML,
        this.userContent()
      );
      
      if (sanitized) {
        this.container().nativeElement.innerHTML = sanitized;
        // Result: <b>User content</b> (script removed)
      }
    }
  }
  ```

  ```typescript Avoid - Unsafe DOM Manipulation theme={null}
  import { Component, ElementRef, viewChild, signal } from '@angular/core';

  @Component({
    selector: 'app-unsafe-dom',
    template: `
      <div #container></div>
      <button (click)="addContent()">Add Content</button>
    `
  })
  export class UnsafeDomComponent {
    private container = viewChild.required<ElementRef>('container');
    userContent = signal('<b>User content</b><script>alert("XSS")</script>');
    
    addContent() {
      // ⚠️ UNSAFE - No sanitization!
      this.container().nativeElement.innerHTML = this.userContent();
      // This executes the malicious script!
    }
  }
  ```
</CodeGroup>

<Warning>
  **Never** use DOM APIs like `innerHTML`, `outerHTML`, `document.write()`, or `Element.setAttribute()` with untrusted data without sanitization.
</Warning>

### Trusting Safe Values

Sometimes applications genuinely need to include executable code or construct potentially dangerous URLs. Use `DomSanitizer` methods to mark values as trusted:

<CodeGroup>
  ```typescript Bypassing Sanitization for Safe URLs theme={null}
  import { Component, inject } from '@angular/core';
  import { DomSanitizer, SafeUrl } from '@angular/platform-browser';

  @Component({
    selector: 'app-bypass-security',
    template: `
      <!-- This would normally be sanitized -->
      <a [href]="dangerousUrl">Click me</a>
    `
  })
  export class BypassSecurityComponent {
    private sanitizer = inject(DomSanitizer);
    
    // Mark the URL as trusted
    dangerousUrl: SafeUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:void(0)');
  }
  ```

  ```typescript Embedding YouTube Videos theme={null}
  import { Component, inject, input, computed } from '@angular/core';
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

  @Component({
    selector: 'app-youtube-player',
    template: `
      <iframe 
        [src]="videoUrl()" 
        width="560" 
        height="315" 
        frameborder="0" 
        allowfullscreen>
      </iframe>
    `
  })
  export class YoutubePlayerComponent {
    private sanitizer = inject(DomSanitizer);
    
    videoId = input.required<string>();
    
    protected videoUrl = computed<SafeResourceUrl>(() => {
      const url = `https://www.youtube.com/embed/${this.videoId()}`;
      return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    });
  }
  ```

  ```typescript All Bypass Methods theme={null}
  import { Component, inject } from '@angular/core';
  import { DomSanitizer } from '@angular/platform-browser';

  @Component({
    selector: 'app-sanitizer-examples',
    template: `...`
  })
  export class SanitizerExamplesComponent {
    private sanitizer = inject(DomSanitizer);
    
    // Bypass HTML sanitization
    trustedHtml = this.sanitizer.bypassSecurityTrustHtml('<b>Trusted HTML</b>');
    
    // Bypass style sanitization
    trustedStyle = this.sanitizer.bypassSecurityTrustStyle('color: red');
    
    // Bypass script sanitization
    trustedScript = this.sanitizer.bypassSecurityTrustScript('console.log("safe")');
    
    // Bypass URL sanitization
    trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:void(0)');
    
    // Bypass resource URL sanitization
    trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl('https://example.com/script.js');
  }
  ```
</CodeGroup>

<Warning>
  **Be extremely careful** when bypassing security. If you trust a malicious value, you introduce a security vulnerability. When in doubt, consult a security expert.
</Warning>

## Content Security Policy (CSP)

Content Security Policy is a defense-in-depth technique to prevent XSS. Configure your web server to return an appropriate `Content-Security-Policy` HTTP header.

### Minimal CSP Configuration

The minimal policy required for a new Angular application:

```http theme={null}
Content-Security-Policy: default-src 'self'; style-src 'self' 'nonce-randomNonceGoesHere'; script-src 'self' 'nonce-randomNonceGoesHere';
```

<Tabs>
  <Tab title="Workspace Config">
    ```json angular.json theme={null}
    {
      "projects": {
        "my-app": {
          "architect": {
            "build": {
              "options": {
                "autoCsp": true
              }
            }
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Application Root">
    ```html index.html theme={null}
    <app ngCspNonce="randomNonceGoesHere"></app>
    ```

    Use this approach if you have server-side templating that can add the nonce to both the header and the HTML.
  </Tab>

  <Tab title="Runtime Provider">
    ```typescript main.ts theme={null}
    import { bootstrapApplication, CSP_NONCE } from '@angular/core';
    import { AppComponent } from './app/app.component';

    bootstrapApplication(AppComponent, {
      providers: [
        {
          provide: CSP_NONCE,
          useValue: globalThis.myRandomNonceValue
        }
      ]
    });
    ```
  </Tab>
</Tabs>

<Note>
  **Critical**: Always ensure that nonces are **unique per request** and not predictable. If an attacker can predict future nonces, they can circumvent CSP protections.
</Note>

### CSP Policy Breakdown

<AccordionGroup>
  <Accordion title="default-src 'self'">
    Allows the page to load all required resources from the same origin. This is the baseline security policy.
  </Accordion>

  <Accordion title="style-src 'self' 'nonce-...'">
    Allows the page to:

    * Load global styles from the same origin (`'self'`)
    * Load styles inserted by Angular with the specified nonce
  </Accordion>

  <Accordion title="script-src 'self' 'nonce-...'">
    Allows the page to:

    * Load JavaScript from the same origin (`'self'`)
    * Load scripts inserted by Angular CLI with the specified nonce
    * Required if using critical CSS inlining
  </Accordion>
</AccordionGroup>

## Trusted Types

Trusted Types is a web platform feature that helps prevent XSS by enforcing safer coding practices. It's recommended to use Trusted Types with Angular.

### Configuring Trusted Types

Configure HTTP headers with Angular policies:

<CodeGroup>
  ```http Basic Angular Policy theme={null}
  Content-Security-Policy: trusted-types angular; require-trusted-types-for 'script';
  ```

  ```http With Sanitizer Bypass theme={null}
  Content-Security-Policy: trusted-types angular angular#unsafe-bypass; require-trusted-types-for 'script';
  ```

  ```http With JIT Compiler theme={null}
  Content-Security-Policy: trusted-types angular angular#unsafe-jit; require-trusted-types-for 'script';
  ```

  ```http With Lazy Loading theme={null}
  Content-Security-Policy: trusted-types angular angular#bundler; require-trusted-types-for 'script';
  ```
</CodeGroup>

### Angular Trusted Type Policies

<CardGroup cols={2}>
  <Card title="angular" icon="shield-check">
    **Required for all apps**

    Used in security-reviewed code internal to Angular. Any inline template values or content sanitized by Angular is treated as safe.
  </Card>

  <Card title="angular#bundler" icon="box">
    **For lazy loading**

    Used by Angular CLI bundler when creating lazy chunk files.
  </Card>

  <Card title="angular#unsafe-bypass" icon="triangle-exclamation">
    **For DomSanitizer bypass**

    Required if using `bypassSecurityTrustHtml`, `bypassSecurityTrustScript`, etc.
  </Card>

  <Card title="angular#unsafe-jit" icon="bolt">
    **For JIT compilation**

    Required if using JIT compiler or platform browser dynamic.
  </Card>
</CardGroup>

## AOT Template Compiler

The Ahead-of-Time (AOT) template compiler prevents template injection vulnerabilities and greatly improves performance.

<CodeGroup>
  ```typescript Secure - AOT Compilation (Default) theme={null}
  // Templates are compiled at build time
  @Component({
    selector: 'app-user-greeting',
    template: `<h1>Hello {{ userName }}</h1>`
  })
  export class UserGreetingComponent {
    userName = 'John';
  }
  // Template is pre-compiled and type-checked
  ```

  ```typescript Insecure - Dynamic Template Generation theme={null}
  // ⚠️ NEVER DO THIS - Security anti-pattern!
  import { Component, Compiler } from '@angular/core';

  @Component({
    selector: 'app-dynamic',
    template: ''
  })
  export class DynamicComponent {
    constructor(private compiler: Compiler) {
      // Dynamically generating templates with user data is dangerous!
      const userTemplate = '<h1>Hello ' + this.getUserInput() + '</h1>';
      // This can execute malicious code!
    }
    
    getUserInput(): string {
      return '<img src=x onerror=alert(1)>';
    }
  }
  ```
</CodeGroup>

<Warning>
  **Never** create Angular templates on the server side or dynamically generate templates with user data. This carries a high risk of template injection vulnerabilities.
</Warning>

## HTTP Security

### XSRF/CSRF Protection

Angular's `HttpClient` has built-in protection against Cross-Site Request Forgery (XSRF/CSRF) attacks:

<CodeGroup>
  ```typescript Default XSRF Protection theme={null}
  import { ApplicationConfig } from '@angular/core';
  import { provideHttpClient } from '@angular/common/http';

  export const appConfig: ApplicationConfig = {
    providers: [
      provideHttpClient()
      // XSRF protection is enabled by default
      // Reads token from 'XSRF-TOKEN' cookie
      // Sends token in 'X-XSRF-TOKEN' header
    ]
  };
  ```

  ```typescript Custom XSRF Configuration theme={null}
  import { ApplicationConfig } from '@angular/core';
  import { provideHttpClient, withXsrfConfiguration } from '@angular/common/http';

  export const appConfig: ApplicationConfig = {
    providers: [
      provideHttpClient(
        withXsrfConfiguration({
          cookieName: 'CUSTOM_XSRF_TOKEN',
          headerName: 'X-Custom-Xsrf-Header'
        })
      )
    ]
  };
  ```

  ```typescript Disabling XSRF Protection theme={null}
  import { ApplicationConfig } from '@angular/core';
  import { provideHttpClient, withNoXsrfProtection } from '@angular/common/http';

  export const appConfig: ApplicationConfig = {
    providers: [
      provideHttpClient(
        withNoXsrfProtection()
        // Only disable if you have alternative protection
      )
    ]
  };
  ```
</CodeGroup>

### How XSRF Protection Works

<Steps>
  <Step title="Server Sets Cookie">
    Server sets a token in a JavaScript-readable cookie called `XSRF-TOKEN` on page load or first GET request
  </Step>

  <Step title="Client Reads Cookie">
    Angular's `HttpClient` reads the token from the cookie
  </Step>

  <Step title="Client Sends Header">
    On mutating requests (POST, PUT, DELETE), the interceptor adds an `X-XSRF-TOKEN` header with the token value
  </Step>

  <Step title="Server Verifies">
    Server verifies that the cookie matches the header value, ensuring the request came from your application
  </Step>
</Steps>

<Info>
  **Why this works**: Only code from your domain can read the cookie and set the header. Malicious sites cannot access cookies from other domains due to the same-origin policy.
</Info>

### XSSI Protection

Angular automatically protects against Cross-Site Script Inclusion (XSSI) attacks:

```typescript theme={null}
// Server response
")]}',\n{\"user\": \"John\", \"role\": \"admin\"}"

// Angular automatically strips the prefix
this.http.get<User>('/api/user').subscribe(user => {
  console.log(user);  // { user: "John", role: "admin" }
});
```

## Server-Side Request Forgery (SSRF) Prevention

Angular includes strict validation for headers to prevent SSRF attacks:

<CodeGroup>
  ```json angular.json Configuration theme={null}
  {
    "projects": {
      "my-app": {
        "architect": {
          "build": {
            "options": {
              "security": {
                "allowedHosts": [
                  "example.com",
                  "*.example.com",
                  "api.trusted-service.com"
                ]
              }
            }
          }
        }
      }
    }
  }
  ```

  ```typescript Runtime Configuration theme={null}
  import { AngularAppEngine } from '@angular/ssr';

  const appEngine = new AngularAppEngine({
    allowedHosts: [
      'example.com',
      '*.trusted-example.com'
    ]
  });
  ```

  ```bash Environment Variable theme={null}
  export NG_ALLOWED_HOSTS="example.com,*.trusted-example.com"
  ```
</CodeGroup>

### Validated Headers

<AccordionGroup>
  <Accordion title="Host and X-Forwarded-Host">
    Validated against a strict allowlist. Cannot contain path separators. Unrecognized hostnames result in CSR page or 400 Bad Request.
  </Accordion>

  <Accordion title="X-Forwarded-Port">
    Must be numeric. Non-numeric values are rejected.
  </Accordion>

  <Accordion title="X-Forwarded-Proto">
    Must be `http` or `https`. Other values are rejected.
  </Accordion>

  <Accordion title="X-Forwarded-Prefix">
    Must not start with multiple `/` or `\\` and cannot contain `.` or `..` path segments.
  </Accordion>
</AccordionGroup>

## Security Checklist

<AccordionGroup>
  <Accordion title="General Security">
    * [ ] Keep Angular updated to the latest stable version
    * [ ] Review security advisories in Angular changelog
    * [ ] Never modify Angular's core files
    * [ ] Audit all uses of security-sensitive APIs
    * [ ] Use AOT compilation in production (enabled by default)
  </Accordion>

  <Accordion title="XSS Prevention">
    * [ ] Never use `innerHTML` with untrusted data
    * [ ] Sanitize data when using DOM APIs directly
    * [ ] Only bypass security when absolutely necessary
    * [ ] Document why security is bypassed for each case
    * [ ] Avoid dynamically generating templates
  </Accordion>

  <Accordion title="CSP and Trusted Types">
    * [ ] Implement Content Security Policy headers
    * [ ] Use unique, unpredictable nonces per request
    * [ ] Enable Trusted Types enforcement
    * [ ] Include appropriate Angular policies
    * [ ] Test CSP in development and staging
  </Accordion>

  <Accordion title="HTTP Security">
    * [ ] Ensure XSRF protection is enabled (default)
    * [ ] Configure custom XSRF cookies if needed
    * [ ] Validate all user input on the server
    * [ ] Use HTTPS in production
    * [ ] Configure allowed hosts for SSR
  </Accordion>
</AccordionGroup>

## Common Vulnerabilities to Avoid

<CardGroup cols={2}>
  <Card title="Template Injection" icon="code">
    ```typescript theme={null}
    // ❌ Never do this
    const template = `<div>${userInput}</div>`;
    ```

    Use data binding instead of string concatenation
  </Card>

  <Card title="Unsafe DOM Access" icon="window">
    ```typescript theme={null}
    // ❌ Avoid direct DOM manipulation
    element.innerHTML = userContent;
    ```

    Use Angular's sanitizer when necessary
  </Card>

  <Card title="Eval and Function Constructor" icon="terminal">
    ```typescript theme={null}
    // ❌ Never use eval with user data
    eval(userInput);
    new Function(userInput)();
    ```

    These execute arbitrary code
  </Card>

  <Card title="Unsafe Resource URLs" icon="link">
    ```typescript theme={null}
    // ❌ Don't trust user-provided URLs
    <iframe [src]="userUrl">
    ```

    Always validate and sanitize URLs
  </Card>
</CardGroup>

## Reporting Security Vulnerabilities

<Warning>
  If you discover a security vulnerability in Angular, please report it responsibly:

  * **Do not** open a public GitHub issue
  * Report at [Google Bug Hunters](https://bughunters.google.com/report)
  * Follow [Google's security philosophy](https://www.google.com/about/appsecurity)
</Warning>

<Card title="Next Steps" icon="book">
  Continue learning about Angular best practices:

  * [Style Guide](/best-practices/style-guide)
  * [Performance Optimization](/best-practices/performance)
  * [Angular Security Guide](https://angular.dev/guide/security)
</Card>
