Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions adev/src/content/reference/errors/NG05201.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Unsafe value used in a resource URL context

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.

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.

The attributes that trigger this check are:

| Element | Attribute(s) |
| ---------- | ------------------ |
| `<base>` | `href` |
| `<embed>` | `src` |
| `<frame>` | `src` |
| `<iframe>` | `src` |
| `<link>` | `href` |
Comment thread
JeanMeche marked this conversation as resolved.
| `<object>` | `codebase`, `data` |

## Debugging the error

This error can also be thrown when calling `DomSanitizer.sanitize()` directly with `SecurityContext.RESOURCE_URL` and a plain string:

```typescript
inject(DomSanitizer).sanitize(SecurityContext.RESOURCE_URL, 'https://example.com'); // throws NG05201
```

`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.

Look for a binding to one of the attributes above or a direct `sanitize()` call:

```html
<iframe [src]="userUrl"></iframe>
```

If the URL comes from a trusted, controlled source, mark it safe using `DomSanitizer.bypassSecurityTrustResourceUrl`:

```typescript
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';

@Component({
selector: 'my-app',
})
export class App {
safeUrl: SafeResourceUrl = inject(DomSanitizer).bypassSecurityTrustResourceUrl(
'https://example.com/embed',
);
}
```

```html
<iframe [src]="safeUrl"></iframe>
```

`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.
2 changes: 1 addition & 1 deletion goldens/public-api/platform-browser/errors.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const enum RuntimeErrorCode {
// (undocumented)
SANITIZATION_UNEXPECTED_CTX = 5202,
// (undocumented)
SANITIZATION_UNSAFE_RESOURCE_URL = 5201,
SANITIZATION_UNSAFE_RESOURCE_URL = -5201,
// (undocumented)
SANITIZATION_UNSAFE_SCRIPT = 5200,
// (undocumented)
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-browser/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const enum RuntimeErrorCode {

// Sanitization-related errors (5200-5300 range)
SANITIZATION_UNSAFE_SCRIPT = 5200,
SANITIZATION_UNSAFE_RESOURCE_URL = 5201,
SANITIZATION_UNSAFE_RESOURCE_URL = -5201,
SANITIZATION_UNEXPECTED_CTX = 5202,

// Animations related errors (5300-5400 range)
Expand Down
Loading