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.
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.
Binding an untrusted value to one of these attributes in a template or host binding throws NG0904 instead.
Debugging the error
Look for a sanitize() call that uses SecurityContext.RESOURCE_URL. The error is thrown for any plain string, even a static-looking URL:
@Component({
selector: 'app-root',
template: `<iframe [src]="url"></iframe>`,
})
export class App {
private readonly sanitizer = inject(DomSanitizer);
url = this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, 'https://example.com/embed'); // throws NG05201
}
If the URL comes from a trusted, controlled source, mark it safe using DomSanitizer.bypassSecurityTrustResourceUrl and bind the result directly:
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<iframe [src]="safeUrl"></iframe>`,
})
export class App {
safeUrl: SafeResourceUrl = inject(DomSanitizer).bypassSecurityTrustResourceUrl(
'https://example.com/embed',
);
}
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.
For more information, see the Security guide.