The library processes SVG content from potentially untrusted sources: user-uploaded files, third-party JSON collections, and remote HTTP APIs. This page documents the six security boundaries, their threat models, and the specific mitigations.
Overview
Six security boundaries protect against the most common attack vectors.
1. Directory path traversal
Threat: a crafted icon name like ../../etc/passwd could read files outside the icon directory.
Mitigation: DirectoryProvider resolves the candidate file path with filepath.EvalSymlinks (which follows symlinks to their real location), then checks that the resolved path starts with the provider's root directory path plus the OS path separator. If the resolved path escapes the root, Get and Has return false.
Request: Get("../../etc/passwd")1. Join root + name: /icons/../../etc/passwd2. EvalSymlinks: /etc/passwd3. Prefix check: /etc/passwd does not start with /icons/4. Result: false (blocked)Symlink attacks are also blocked. A symlink inside the icon directory that points outside it is resolved by EvalSymlinks, and the prefix check catches the escape.
2. SVG XSS
Threat: SVG files can contain <script> elements, on* event handlers, javascript: URIs, <foreignObject> with arbitrary HTML, and external resource references.
Mitigation: the library applies a 9-stage regex pipeline to all SVG inner content. This pipeline runs automatically inside FromFile, FromString, and the Iconify JSON parsing path. There is no way to bypass sanitization through the standard constructors.
The pipeline strips:
<script>,<foreignObject>,<title>,<desc>elements (entire element including content).on*event handler attributes.javascript:URIs (replaced withhref="#").- External
https?://URLs in<use>and<image>href attributes. - XML comments (which could hide malicious content from naive scanners).
3. Attribute name XSS
Threat: a crafted attribute name could break out of the SVG element. For example, an attribute named onclick or " onload="evil() could inject event handlers.
Mitigation: Icon.renderAttributes() (called by ToHTML) validates every attribute name against the regex:
^[a-zA-Z_:][\w:.\-]*$Names that do not match are silently dropped from the output. This allows standard SVG attributes (viewBox, stroke-width, xmlns:xlink) while rejecting names containing spaces, quotes, or other characters that could break the attribute syntax.
4. Attribute value XSS
Threat: an attribute value like " onload="evil() could inject event handlers if rendered without escaping.
Mitigation: all attribute values are escaped with html.EscapeString() before being written into the <svg> element by ToHTML. This converts <, >, &, ", and ' to their HTML entity equivalents.
// Input: data-x="<>&\"'"// Output: data-x="<>&"'"The escaping is unconditional and applied to every attribute value, including those from trusted sources.
5. Iconify SSRF
Threat: the IconifyProvider makes HTTP requests. If an attacker can control the host list, the provider could be used as a server-side request forgery (SSRF) vector to probe internal networks.
Mitigation: the provider only contacts hosts in its configured host list. The default list contains three known Iconify API servers:
https://api.iconify.designhttps://api.simplesvg.comhttps://api.unisvg.com
The WithHosts option allows overriding this list, but the caller must provide the replacement list explicitly. There is no mechanism for user input to influence the host list at runtime unless the application code exposes it.
The HTTP request URL is constructed from the configured host, the provider's prefix (set at construction time), and the icon name (URL-escaped via url.PathEscape and url.QueryEscape). The response body is limited to 1 MB via io.LimitReader.
Limitation: this is not a hard allowlist in the sense that WithHosts can be called with arbitrary URLs. The protection relies on the application developer not exposing WithHosts to untrusted input. The default configuration is safe.
6. JSON alias loops
Threat: an Iconify JSON collection could contain a circular alias chain (a -> b -> c -> a), causing infinite recursion during icon resolution.
Mitigation: JsonCollectionProvider.resolveAlias tracks recursion depth and stops at 10. If the depth limit is reached, the alias resolution returns nil, and Get returns (nil, false).
{ "aliases": { "a": {"parent": "b"}, "b": {"parent": "c"}, "c": {"parent": "a"} }}Requesting icon "a" follows the chain a -> b -> c -> a and hits the depth limit at step 4. The icon is treated as not found rather than causing a stack overflow.
The depth limit of 10 is sufficient for legitimate alias chains (which rarely exceed 2-3 levels) while preventing pathological cases.
See also
- SVG Sanitization: the nine-stage pipeline that implements boundary #2
- Providers API reference: constructor signatures and functional options including
WithHosts()
Summary
| Boundary | Threat | Mitigation | Location |
|---|---|---|---|
| Directory paths | Path traversal | filepath.EvalSymlinks + prefix check |
directory_provider.go |
| SVG content | XSS via scripts/handlers/URIs | 9-stage sanitization pipeline | internal/svgparse/svgparse.go |
| Attribute names | XSS via crafted keys | Regex validation, invalid names dropped | icon.go |
| Attribute values | XSS via injection | html.EscapeString() on all values |
icon.go |
| Iconify URLs | SSRF | Configured host list (defaults to 3 Iconify hosts) | iconify_provider.go |
| JSON aliases | Infinite recursion | Depth limit of 10 | json_provider.go |