angular/angular · warning
WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECUR
Error message
WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECURITY_URL}) What it means
_sanitizeUrl - used for URL-context bindings like [href], [src], and sanitize(SecurityContext.URL, …) - tested the value against SAFE_URL_PATTERN: it must not start with javascript: and must either begin with a valid scheme ([a-z0-9+.-]+:) or be a relative/scheme-relative path without masked colons (e.g. javascript:). Failing values are prefixed with 'unsafe:' (making the link inert) and dev mode logs this warning showing the offending URL.
Source
Thrown at packages/core/src/sanitization/url_sanitizer.ts:44
* (before port).
*
* The pattern disallows &, used in HTML entity declarations before
* one of the characters in [/?#]. This disallows HTML entities used in the
* protocol name, which should never happen, e.g. "http" for "http".
* It also disallows HTML entities in the first path part of a relative path,
* e.g. "foo<bar/baz". Our existing escaping functions should not produce
* that. More importantly, it disallows masking of a colon,
* e.g. "javascript:...".
*
* This regular expression was taken from the Closure sanitization library.
*/
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
export function _sanitizeUrl(url: string): string {
url = String(url);
if (url.match(SAFE_URL_PATTERN)) return url;
if (typeof ngDevMode === 'undefined' || ngDevMode) {
console.warn(`WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECURITY_URL})`);
}
return 'unsafe:' + url;
}
View on GitHub (pinned to 51cb07e980)
Solutions
- Fix the URL value: use a real scheme (https://…), a relative path, or '#' placeholders instead of javascript: URLs.
- Replace javascript: href links with type="button" buttons bound to (click).
- If the URL is guaranteed safe by construction, wrap it with DomSanitizer.bypassSecurityTrustUrl in the component and bind the SafeUrl.
Example fix
<!-- before --> <a [href]="'javascript:void(0)'" (click)="open()">Open</a> <!-- after --> <button type="button" (click)="open()">Open</button>
Defensive patterns
Strategy: type-guard
Validate before calling
// Mirror Angular's SAFE_URL_PATTERN before assigning the value
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
function safeUrlOrNull(url: string): string | null {
const u = String(url);
return u.match(SAFE_URL_PATTERN) ? u : null;
} Type guard
function isSafeUrl(url: unknown): url is string {
return typeof url === 'string' && /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i.test(url);
} Prevention
- Never bind javascript: URLs; use buttons with (click).
- Interpolate URLs through a sanitizer/validator when they come from user input.
- Guard assembled URLs when components may be missing (avoid 'undefined' hrefs).
- Use DomSanitizer.bypassSecurityTrustUrl only for URLs constructed from trusted constants.
When it happens
Trigger: [href]="javascript:void(0)" or a value like 'javascript:alert(1)' with a masked colon; a malformed URL containing characters such as '<' that fail the pattern; URLs assembled from user input that end up as 'undefined' or contain encoded colons.
Common situations: Legacy markup migrated to property bindings; dynamic URL construction from form input; template literals that produce garbage when a variable is missing; sanitizing deep-link parameters.
Related errors
- WARNING: ignoring unsafe attribute ${lowerAttrName} on eleme
- WARNING: sanitizing HTML stripped some content, see ${XSS_SE
- PROTOCOL_RELATIVE_URL_NOT_ALLOWED
- SUSPICIOUS_URL_CHANGE_ORIGIN
- JSONP support is deprecated as it can cause XSS vulnerabilit
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/830038d4beddf59a.
Report an issue: GitHub.