# Angular

{% hint style="warning" %}
This page is about [Angular](https://angular.dev/) (V2+), *not* [AngularJS](https://angularjs.org/) (V1.x). Check out the [Cross-Site Scripting (XSS)](/web/client-side/cross-site-scripting-xss.md#angularjs) page for ways to achieve XSS using Client-Side Template Injection in that older version of the framework.
{% endhint %}

### innerHTML

The [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) property of HTML elements is notorious in the world of [Cross-Site Scripting (XSS)](/web/client-side/cross-site-scripting-xss.md). This is because in regular JavaScript, it will render a string to the DOM, which may include JavaScript code like `<img src onerror=alert(origin)>`.

Because you can still write raw JavaScript in Angular, the following code will still be vulnerable in the same way:

```javascript
elem.innerHTML = `<p>${input}</p>`
```

The more common way to do this, however, is using a *bind*:

```html
<p [innerHTML]="input"></p>
```

`input` here refers to a variable with that name, defined in JavaScript. While this may look similar, the bind example will apply the [Angular Sanitizer](https://angular.dev/best-practices/security#sanitization-example) ([source code](https://github.com/angular/angular/blob/main/packages/core/src/sanitization/html_sanitizer.ts)). This removes any dangerous HTML elements or attributes.

The filter is pretty tight, and any bypass would be a vulnerability in Angular itself. It is so restricted that some developers will notice intended markup being removed, so they **disable the sanitization**. This can be done using the [`bypassSecurityTrustHtml()`](https://angular.dev/api/platform-browser/DomSanitizer#bypassSecurityTrustHtml) function.

```typescript
constructor(private sanitizer: DomSanitizer) {
  this.input = this.sanitizer.bypassSecurityTrustHtml("<img src onerror=alert(origin)>");
}
```

This is often companied by some sort of sanitizer, which you should carefully review to determine if there are any bypasses possible in this potentially less secure version instead of the Angular default.

Another indirect way to put a string into the DOM is using [`DOMParser.parseFromString()`](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString). Because Angular doesn't see this, it will bypass its sanitizer too:

```typescript
@ViewChild("p") p: ElementRef | undefined;
ngAfterViewInit() {
  const html = new DOMParser().parseFromString("<img src onerror=alert(origin)>", "text/html").body.firstChild;
  this.p?.nativeElement.appendChild(html);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.jorianwoltjer.com/web/frameworks/angular.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
