Skip to content

fix(compiler): sanitize dynamic href and xlink:href bindings on SVG a…#68868

Open
alan-agius4 wants to merge 2 commits into
angular:mainfrom
alan-agius4:svg-a-link
Open

fix(compiler): sanitize dynamic href and xlink:href bindings on SVG a…#68868
alan-agius4 wants to merge 2 commits into
angular:mainfrom
alan-agius4:svg-a-link

Conversation

@alan-agius4
Copy link
Copy Markdown
Contributor

… elements

Dynamic bindings to href and xlink:href attributes on SVG <a> elements (<svg:a>) were previously unmapped in the DOM security schema. As a result, they bypassed sanitization completely, creating a potential XSS vulnerability if bound to untrusted user inputs (e.g., javascript: URLs).

This fix mitigates this risk by:

  1. Registering href and xlink:href on <svg:a> elements under the SecurityContext.URL context in both the compiler and core DOM security schemas.

  2. Enabling template compilation to output runtime URL sanitization checks (ɵɵsanitizeUrl) on these attributes.

  3. Adding regression and verification test cases to ensure dynamic SVG link bindings are safely sanitized at runtime while static values are correctly allowed.

… elements

Dynamic bindings to `href` and `xlink:href` attributes on SVG `<a>` elements (`<svg:a>`) were previously unmapped in the DOM security schema. As a result, they bypassed sanitization completely, creating a potential XSS vulnerability if bound to untrusted user inputs (e.g., `javascript:` URLs).

This fix mitigates this risk by:

1. Registering `href` and `xlink:href` on `<svg:a>` elements under the `SecurityContext.URL` context in both the compiler and core DOM security schemas.

2. Enabling template compilation to output runtime URL sanitization checks (`ɵɵsanitizeUrl`) on these attributes.

3. Adding regression and verification test cases to ensure dynamic SVG link bindings are safely sanitized at runtime while static values are correctly allowed.
@alan-agius4 alan-agius4 requested a review from AndrewKushnir May 21, 2026 18:51
@alan-agius4 alan-agius4 added action: review The PR is still awaiting reviews from at least one requested reviewer target: rc This PR is targeted for the next release-candidate labels May 21, 2026
@pullapprove pullapprove Bot requested a review from josephperrott May 21, 2026 18:51
@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label May 21, 2026
@ngbot ngbot Bot added this to the Backlog milestone May 21, 2026
…ntSchemaRegistry

Custom XML/XHTML namespaced elements (e.g., <xhtml:a>) fall back to the standard HTML namespace during element creation at compile-time/runtime. However, their property and security context lookups inside the schema registry were incorrectly performed using the full namespaced tag name (e.g., :xhtml:a), which bypassed the default a|href sanitization registry and incorrectly returned SecurityContext.NONE instead of SecurityContext.URL.

This commit introduces tag name normalization inside DomElementSchemaRegistry for custom namespaces (other than the built-in svg and math namespaces). Custom namespaced tag names are now normalized to their simple HTML element counterparts for all registry queries, ensuring that correct property schema validation and dynamic security sanitization rules (such as URL sanitization) are enforced at runtime.
Copy link
Copy Markdown
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alan-agius4 thanks for the improvement! I've left a comment with a proposed refactoring, but please don't treat it as blocking.


const colonIdx = tagName.indexOf(':');
if (colonIdx > 0) {
const ns = tagName.substring(0, colonIdx);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in this part of the function looks very similar to what's happening inside of the splitNsName helper, can we reconcile the logic and have better handling inside of splitNsName? In this case, this whole function may look like this (ask splitNsName to split into logical pieces and normalize for svg/mathml namespaces):

function normalizeTagName(tagName: string): string {
    const [ns, name] = splitNsName(tagName, false);
    return ns === SVG_NAMESPACE || ns === MATH_ML_NAMESPACE ? `:${ns}:${name}` : name;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer area: compiler Issues related to `ngc`, Angular's template compiler target: rc This PR is targeted for the next release-candidate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants