{"record":{"id":"830038d4beddf59a","repo":"angular/angular","slug":"warning-sanitizing-unsafe-url-value-url-see","errorCode":null,"errorMessage":"WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECURITY_URL})","messagePattern":"WARNING: sanitizing unsafe URL value (.+?) \\(see (.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/core/src/sanitization/url_sanitizer.ts","lineNumber":44,"sourceCode":" *     (before port).\n *\n * The pattern disallows &, used in HTML entity declarations before\n * one of the characters in [/?#]. This disallows HTML entities used in the\n * protocol name, which should never happen, e.g. \"h&#116;tp\" for \"http\".\n * It also disallows HTML entities in the first path part of a relative path,\n * e.g. \"foo&lt;bar/baz\".  Our existing escaping functions should not produce\n * that. More importantly, it disallows masking of a colon,\n * e.g. \"javascript&#58;...\".\n *\n * This regular expression was taken from the Closure sanitization library.\n */\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\\/?#]*(?:[\\/?#]|$))/i;\nexport function _sanitizeUrl(url: string): string {\n  url = String(url);\n  if (url.match(SAFE_URL_PATTERN)) return url;\n\n  if (typeof ngDevMode === 'undefined' || ngDevMode) {\n    console.warn(`WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECURITY_URL})`);\n  }\n\n  return 'unsafe:' + url;\n}\n","sourceCodeStart":26,"sourceCodeEnd":49,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/core/src/sanitization/url_sanitizer.ts#L26-L49","documentation":"_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&#58;). Failing values are prefixed with 'unsafe:' (making the link inert) and dev mode logs this warning showing the offending URL.","triggerScenarios":"[href]=\"javascript:void(0)\" or a value like 'java&#115;cript: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.","commonSituations":"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.","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."],"exampleFix":"<!-- before -->\n<a [href]=\"'javascript:void(0)'\" (click)=\"open()\">Open</a>\n\n<!-- after -->\n<button type=\"button\" (click)=\"open()\">Open</button>","handlingStrategy":"type-guard","validationCode":"// Mirror Angular's SAFE_URL_PATTERN before assigning the value\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\\/?#]*(?:[\\/?#]|$))/i;\nfunction safeUrlOrNull(url: string): string | null {\n  const u = String(url);\n  return u.match(SAFE_URL_PATTERN) ? u : null;\n}","typeGuard":"function isSafeUrl(url: unknown): url is string {\n  return typeof url === 'string' && /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\\/?#]*(?:[\\/?#]|$))/i.test(url);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["xss","sanitization","url","security"],"backgroundTag":"unsafe-url-sanitized","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}