Skip to content

Commit 10c5a06

Browse files
committed
docs: fix NG05201 error page trigger and add it to the overview
The NG05201 page said the error is thrown when binding an untrusted value to a resource URL attribute such as `<iframe [src]>`, but template and host bindings are checked by core and throw NG0904. NG05201 only comes from calling `DomSanitizer.sanitize()` with `SecurityContext.RESOURCE_URL`. Rewrite the page around the direct `sanitize()` call, link to NG0904 for bindings, align its structure with the NG0904 page, and add NG05201 to the errors overview.
1 parent e699fd7 commit 10c5a06

2 files changed

Lines changed: 21 additions & 31 deletions

File tree

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,34 @@
1-
# Unsafe value used in a resource URL context
1+
# Unsafe resource URL passed to DomSanitizer
22

3-
Angular throws this error when you bind a value to an attribute that loads an external resource — like `<iframe src>`, or `<link href>` — and that value hasn't been explicitly marked as trusted.
3+
Angular throws this error, with the message `unsafe value used in a resource URL context`, when `DomSanitizer.sanitize()` is called with `SecurityContext.RESOURCE_URL` and a value that hasn't been explicitly marked as trusted.
44

5-
Resource URLs are treated differently from regular URLs. Angular can sanitize a plain URL (stripping `javascript:` schemes and so on), but it can't make an arbitrary resource URL safe because these attributes cause the browser to fetch and execute external content. So Angular rejects untrusted values rather than trying to sanitize them.
5+
Resource URLs are treated differently from regular URLs. Angular can sanitize a plain URL, but it can't make an arbitrary resource URL safe because resource URL attributes, like `<iframe src>` or `<link href>`, cause the browser to fetch and execute external content. So `sanitize()` rejects untrusted values rather than trying to sanitize them.
66

7-
The attributes that trigger this check are:
8-
9-
| Element | Attribute(s) |
10-
| ---------- | ------------------ |
11-
| `<base>` | `href` |
12-
| `<embed>` | `src` |
13-
| `<frame>` | `src` |
14-
| `<iframe>` | `src` |
15-
| `<link>` | `href` |
16-
| `<object>` | `codebase`, `data` |
7+
Binding an untrusted value to one of these attributes in a template or host binding throws [NG0904](errors/NG0904) instead.
178

189
## Debugging the error
1910

20-
This error can also be thrown when calling `DomSanitizer.sanitize()` directly with `SecurityContext.RESOURCE_URL` and a plain string:
21-
22-
```typescript
23-
inject(DomSanitizer).sanitize(SecurityContext.RESOURCE_URL, 'https://example.com'); // throws NG05201
24-
```
25-
26-
`sanitize()` cannot make an arbitrary string safe in a resource URL context. Either use `bypassSecurityTrustResourceUrl` if the value is fully under your control, or bind the value to a regular URL attribute that Angular can sanitize.
27-
28-
Look for a binding to one of the attributes above or a direct `sanitize()` call:
11+
Look for a `sanitize()` call that uses `SecurityContext.RESOURCE_URL`. The error is thrown for any plain string, even a static-looking URL:
2912

30-
```html
31-
<iframe [src]="userUrl"></iframe>
13+
```angular-ts
14+
@Component({
15+
selector: 'app-root',
16+
template: `<iframe [src]="url"></iframe>`,
17+
})
18+
export class App {
19+
private readonly sanitizer = inject(DomSanitizer);
20+
url = this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, 'https://example.com/embed'); // throws NG05201
21+
}
3222
```
3323

34-
If the URL comes from a trusted, controlled source, mark it safe using `DomSanitizer.bypassSecurityTrustResourceUrl`:
24+
If the URL comes from a trusted, controlled source, mark it safe using `DomSanitizer.bypassSecurityTrustResourceUrl` and bind the result directly:
3525

36-
```typescript
26+
```angular-ts
3727
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
3828
3929
@Component({
40-
selector: 'my-app',
30+
selector: 'app-root',
31+
template: `<iframe [src]="safeUrl"></iframe>`,
4132
})
4233
export class App {
4334
safeUrl: SafeResourceUrl = inject(DomSanitizer).bypassSecurityTrustResourceUrl(
@@ -46,8 +37,6 @@ export class App {
4637
}
4738
```
4839

49-
```html
50-
<iframe [src]="safeUrl"></iframe>
51-
```
40+
CRITICAL: `bypassSecurityTrustResourceUrl` is an escape hatch, not a sanitizer. Never pass user-supplied URLs through it — that would allow an attacker to load arbitrary content, including malicious scripts. Only use it when the value is fully under your control.
5241

53-
`bypassSecurityTrustResourceUrl` is an escape hatch, not a sanitizer. Never pass user-supplied URLs through it — that would allow an attacker to load arbitrary content, including malicious scripts. Only use it when the value is fully under your control.
42+
For more information, see the [Security guide](best-practices/security#trusting-safe-values).

‎adev/src/content/reference/errors/overview.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
| `NG05000` | [Hydration with unsupported Zone.js instance.](errors/NG05000) |
5252
| `NG05104` | [Root element was not found.](errors/NG05104) |
5353
| `NG05106` | [Insertion reference node not found](errors/NG05106) |
54+
| `NG05201` | [Unsafe resource URL passed to DomSanitizer](errors/NG05201) |
5455
| `NG05703` | [Suspicious URL origin change during SSR](errors/NG05703) |
5556

5657
## Compiler errors

0 commit comments

Comments
 (0)