當範本或宿主繫結把載入外部資源的屬性(例如 <iframe src> 或 <link href>)設定為未被明確標示為受信任的值時,Angular 會拋出此錯誤,訊息為 unsafe value used in a resource URL context。
資源 URL 的處理方式與一般 URL 不同。Angular 可以淨化普通的 URL,但無法讓任意的資源 URL 變安全,因為這些屬性會讓瀏覽器擷取並執行外部內容。因此 Angular 會拒絕不受信任的值,而不是嘗試淨化它們。
觸發此檢查的屬性如下:
| Element | Attribute(s) |
|---|---|
<base> |
href |
<embed> |
src |
<frame> |
src |
<iframe> |
src |
<link> |
href |
<object> |
codebase, data |
除錯方式
把任何普通字串繫結到上述屬性之一時都會拋出此錯誤,即使是看起來像靜態的 URL:
@Component({
selector: 'app-root',
template: `<iframe [src]="url"></iframe>`,
})
export class App {
url = 'https://example.com/embed';
}
把值以 SecurityContext.URL 傳給 DomSanitizer.sanitize() 也沒有幫助。sanitize() 傳回的是普通字串,而普通字串在資源 URL 情境中永遠不會被接受:
@Component({
selector: 'app-root',
template: `<iframe [src]="sanitized"></iframe>`,
})
export class App {
private readonly sanitizer = inject(DomSanitizer);
sanitized = this.sanitizer.sanitize(SecurityContext.URL, 'https://example.com/embed'); // still throws NG0904
}
改以 SecurityContext.RESOURCE_URL 呼叫 sanitize() 同樣會拋出錯誤,但錯誤碼是 NG05201,因為 sanitize() 無法讓任意字串在資源 URL 情境中變安全。
如果該 URL 來自受信任且受控制的來源,請使用 DomSanitizer.bypassSecurityTrustResourceUrl 把它標示為安全:
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
import {Component, inject} from '@angular/core';
@Component({
selector: 'app-root',
template: `<iframe [src]="safeUrl"></iframe>`,
})
export class App {
safeUrl: SafeResourceUrl = inject(DomSanitizer).bypassSecurityTrustResourceUrl(
'https://example.com/embed',
);
}
CRITICAL: bypassSecurityTrustResourceUrl 是逃生口,不是淨化器。絕不要把使用者提供的 URL 傳給它,那會讓攻擊者載入任意內容,包括惡意指令碼。只有在該值完全由你控制時才使用它。
更多資訊請見安全性指南。