Technical

SVG Link Security: Validate href and xlink:href Safely

SVG Genie TeamSVG Design Expert & Technical Writer at SVG Genie
||9 min read

Reviewed by SVG Genie Editorial Team

A logo upload can look like ordinary paths while hiding a clickable link, remote fetch, or legacy xlink:href value. If your sanitizer checks only <script>, that URL can survive and behave differently when the SVG is opened directly, embedded inline, or processed by another tool.

Use this fast rule:

For untrusted SVG artwork, allow only the URL forms each element genuinely needs. Keep local fragments only after resolving their targets, remove external links by default, inspect both href and xlink:href, and reject conflicting values.

That policy is easier to audit than a blacklist of suspicious strings. For a complete upload pipeline, pair it with the SVG upload security checklist.

Safe local SVG fragment links and blocked JavaScript, data, and remote URL links

What is SVG link security?

SVG link security is the practice of validating every URL-bearing SVG attribute according to the element, rendering context, and destination it controls. It covers clickable anchors, reused symbols, images, filters, gradients, masks, animations, styles, and other features that can refer to local IDs or external resources.

The important distinction is that href does not mean one universal thing. On an <a> element it can navigate a user. On <use> it can identify reusable graphics. On <image> it can load image data. A safe value for one context may be unnecessary or dangerous in another.

MDN's href attribute reference lists the SVG elements that accept the attribute and explains that its meaning depends on the element. Build rules per element instead of running one loose URL regex across the file.

Which SVG elements can carry links or references?

The main URL-bearing elements include <a>, <use>, <image>, animation elements, and several paint or resource elements. CSS declarations can introduce more URLs through url(...), so attribute checks alone are not a complete sanitizer.

ContextTypical valueSafest upload defaultWhy
<a href>Web destinationRemove, or allow HTTPS under policyCan navigate the viewer
<use href>#iconAllow validated local fragment onlyClones referenced SVG content
<image href>Data or remote imageRemove or rewrite to trusted local assetCan embed or fetch another resource
<linearGradient href>#baseGradientAllow validated local fragment onlyInherits paint-server attributes
<filter>, <mask>, <clipPath> referencesurl(#effect)Allow validated local fragment onlyChanges rendering through another node
Animation target reference#shapeRemove animation or validate targetCan alter properties over time
CSS url(...)Fragment, data, or remote URLParse CSS; allow local fragments onlyBypasses attribute-only checks

For general-purpose logos and icons, local fragment references usually provide everything the artwork needs. Removing navigation and network access reduces both security risk and confusing external dependencies.

How should href and xlink:href be handled?

Read both attributes, normalize them into one internal value, and reject the element if they disagree. Modern SVG uses href; xlink:href is legacy, but older design applications and existing assets still produce it.

MDN marks xlink:href as deprecated and recommends href, while also documenting compatibility behavior.

Use this sequence:

  1. Parse the file as XML with DTD and external entities disabled.
  2. Read href and the correctly namespaced xlink:href attribute from the parsed node.
  3. Decode XML character references as part of parsing, not with ad hoc replacements.
  4. Trim surrounding ASCII whitespace and reject control characters.
  5. If both attributes exist and differ after normalization, reject the node.
  6. Apply an element-specific fragment or URL policy.
  7. Rewrite an allowed legacy value to href in the clean output.

Do not search raw text for javascript: and call the job finished. Entity encoding, mixed whitespace, namespaces, CSS, and parser repairs can all create differences between what a substring check sees and what the renderer interprets.

Which href values should an SVG sanitizer allow?

For untrusted image uploads, use a small allowlist: approved local fragments for reference elements and no link destination for everything else. Add normalized HTTPS URLs only when clickable outbound links are an explicit product requirement.

Value shapeExampleRecommended decision
Same-document fragment#logo-markAllow after target validation
Relative fileicons.svg#markReject for self-contained uploads
HTTPS URLhttps://example.com/Reject by default; allow only under an explicit link policy
Protocol-relative URL//example.com/file.svgReject
Data URLdata:image/svg+xml,...Reject for untrusted SVG
Executable or unknown schemejavascript:...Reject
Empty, malformed, or control-character valuevariesReject or remove

If your product must preserve clickable links, parse the destination with a standards-compliant URL parser, require https:, compare the normalized hostname against an allowlist when appropriate, and add rel="noopener noreferrer" for links that open a new browsing context. OWASP's Unvalidated Redirects and Forwards Cheat Sheet recommends allowlisting trusted destinations rather than relying on user-controlled redirect targets.

Why are local fragment links not automatically safe?

A fragment such as #icon stays inside the document, but the target can still be missing, duplicated, unsupported, or connected to content your sanitizer failed to inspect. Safety depends on both the reference string and the resolved target.

For every allowed fragment:

  • require a conservative ID syntax;
  • build the ID map from the sanitized tree;
  • reject duplicate IDs;
  • require exactly one matching target;
  • allow only target types appropriate to the source element;
  • inspect the target and all descendants;
  • detect cycles in nested references;
  • cap reference depth and expanded rendering cost.

The dedicated <use> security guide explains clone graphs and nested symbol limits. Apply the same principle to gradients, masks, filters, and clip paths: validate what the reference resolves to, not merely the fact that it begins with #.

How do rendering contexts change SVG link risk?

The same file can have different capabilities when displayed as an image, opened as its own document, inserted inline into HTML, or processed by server-side software. Sanitization must assume the most capable context in which your product or a downstream user may place the file.

An <img src="asset.svg"> boundary can restrict behaviors that an inline <svg> does not. But users may download the asset and open it directly, a CMS may inline it for styling, or an optimization tool may transform the markup. Treat browser containment as defense in depth, not a substitute for cleaning the source.

Use an isolated, no-network preview while reviewing untrusted files. The SVG sandbox preview guide shows how to separate inspection from the main application origin. If the asset does not need to remain interactive, a rasterized preview is the simpler choice.

What is a practical href validation algorithm?

A practical validator first classifies the element and attribute, then classifies the parsed destination. It never gives every href the permissions of the most flexible use case.

validateReference(element, href, xlinkHref):
  value = normalizeAndReconcile(href, xlinkHref)
  if value is invalid or conflicting: reject

  policy = policyFor(element)

  if value starts with "#":
    if policy does not allow fragments: reject
    target = resolveUniqueSanitizedId(value)
    if target is not allowed for element: reject
    validateReferenceGraph(target)
    return keepAsHref(value)

  if policy allows externalNavigation:
    url = parseAbsoluteUrl(value)
    if url.scheme != "https": reject
    if url.host is not allowed: reject
    return keepNormalized(url)

  reject

Keep the output deterministic. Remove unused namespace declarations, serialize allowed legacy references as href, and run the cleaned file through a second parse before storing it. A parse–sanitize–serialize–parse test catches malformed output and makes security regression tests more realistic.

What is the fastest SVG link security checklist?

The shortest defensible workflow is to inventory every URL-bearing feature, keep only necessary local fragments, validate resolved targets, remove navigation and remote loading by default, and test the serialized result in an isolated environment with network requests blocked.

  • Parse XML instead of filtering raw strings.
  • Disable DTD and external entity resolution.
  • Check href, namespaced xlink:href, and CSS url(...).
  • Reject conflicting href and xlink:href values.
  • Use rules specific to <a>, <use>, <image>, paint servers, and animation.
  • Allow only validated local fragments for ordinary artwork.
  • Reject javascript:, data URLs, protocol-relative URLs, and unknown schemes.
  • Resolve fragments against unique IDs in the sanitized tree.
  • Walk referenced descendants and reject cycles.
  • Block network access in preview and processing environments.
  • Reparse the serialized clean SVG before saving it.
  • Keep regression fixtures for encoded, namespaced, and conflicting values.

When you need to inspect and simplify a file before publishing, open a copy in the SVG Editor, remove unnecessary interactive features, and export a self-contained asset. For document-wide remote-resource rules, continue with the SVG external reference security guide.

FAQ

Can an SVG link contain JavaScript?

Untrusted SVG can place dangerous or unexpected schemes in URL-bearing attributes. Do not depend on browser behavior. Parse the value, reject executable and unknown schemes, and allow only the link forms your product actually needs.

Is xlink:href still valid in SVG?

xlink:href is a legacy form. Modern SVG uses href, but sanitizers should inspect both because uploaded files and older tools may still emit xlink:href. Reject the element when the two attributes conflict.

Should an SVG sanitizer allow external links?

For logos, icons, and ordinary image uploads, the safest default is no external links. If clickable links are a required feature, allow only normalized HTTPS destinations under an explicit host policy and add browser protections at render time.

Are fragment links such as #icon safe?

A local fragment is safer than a network URL, but it still needs validation. Require a valid fragment syntax, a unique target ID, an allowed target element, and a sanitized referenced subtree.

What should happen when href and xlink:href disagree?

Reject the element or remove both attributes. Choosing one value silently can create a mismatch between sanitizer assumptions, editing tools, and browser rendering behavior.

Create your own SVG graphics with AI

Describe what you need, get a production-ready vector in seconds. No design skills required.

Try SVG Genie Freearrow_forward

About This Article

This article was written by SVG Genie Team based on hands-on testing with SVG Genie’s tools and years of experience in vector design and web graphics. All recommendations reflect real-world usage and are reviewed by the SVG Genie editorial team for accuracy.

About the Author

SVG Genie Team

SVG Design Expert & Technical Writer at SVG Genie

SVG Genie Team is a vector design specialist and technical writer at SVG Genie with years of hands-on experience in SVG tooling, AI-assisted design workflows, and web graphics optimization. Their work focuses on making professional vector design accessible to everyone.

More articles by SVG Genie Teamarrow_forward

Ready to Create Your Own Vectors?

Start designing with AI-powered precision today.

Get Started Freearrow_forward