siyuan-note/siyuan · error
svg directives are not allowed
Error message
svg directives are not allowed
What it means
The input contains an XML directive (the token between '<!' and '>' — usually a DOCTYPE) that is not a benign, subset-free SVG DOCTYPE. Internal DTD subsets can declare entities (XXE / billion-laughs style attacks and entity expansion tricks), so SanitizeSVG hard-rejects any directive whose body fails isBenignSVGDoctype (anything with an internal subset '[...]' or non-svg root name).
Source
Thrown at kernel/util/misc.go:441
continue
}
if (!rootSeen || rootClosed) && strings.TrimSpace(string(typed)) != "" {
return "", fmt.Errorf("svg contains text outside the root element")
}
if rootSeen && !rootClosed {
if err = encoder.EncodeToken(typed); err != nil {
return "", fmt.Errorf("render svg failed: %w", err)
}
}
case xml.Comment:
if skipDepth == 0 && rootSeen && !rootClosed {
if err = encoder.EncodeToken(typed); err != nil {
return "", fmt.Errorf("render svg failed: %w", err)
}
}
case xml.Directive:
if !isBenignSVGDoctype(string(typed)) {
return "", fmt.Errorf("svg directives are not allowed")
}
// 良性 DOCTYPE 声明不写入输出,与 XML 声明(ProcInst)的处理方式一致,不影响浏览器渲染
case xml.ProcInst:
// XML 声明和处理指令不影响 SVG 图像内容,输出时统一省略。
}
}
if !rootSeen || !rootClosed || depth != 0 || skipDepth != 0 || len(elementStack) != 0 {
return "", fmt.Errorf("svg root element is incomplete")
}
if err := encoder.Close(); err != nil {
return "", fmt.Errorf("render svg failed: %w", err)
}
return buf.String(), nil
}
func preserveXMLName(name xml.Name) xml.Name {
if name.Space != "" {View on GitHub (pinned to 8641553a1f)
Solutions
- Delete the DOCTYPE declaration entirely — it is optional and never needed for rendering
- If DTD validation metadata matters, keep it in a separate file and ship only the bare <svg> markup
- For batch processing, strip directives with a regex on '<!DOCTYPE' ... '>' before calling SanitizeSVG
- Never re-enable entity declarations; expand any entities in text content to literal characters beforehand
Example fix
// before
SanitizeSVG("<!DOCTYPE svg [<!ENTITY x \"y\">]><svg>...</svg>") // svg directives are not allowed
// after
SanitizeSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">...</svg>") Defensive patterns
Strategy: validation
Validate before calling
func stripDOCTYPE(input string) string {
i := strings.Index(input, "<!DOCTYPE")
if i < 0 { return input }
j := strings.Index(input[i:], ">")
if j < 0 { return input }
return strings.TrimSpace(input[:i] + input[i+j+1:])
} Type guard
func hasInternalSubset(input string) bool {
i := strings.Index(strings.ToUpper(input), "<!DOCTYPE")
return i >= 0 && strings.Contains(input[i:], "[") && strings.Contains(input[i:], "]")
} Try / catch
clean, err := util.SanitizeSVG(input)
if err != nil && strings.Contains(err.Error(), "directives are not allowed") {
input = stripDOCTYPE(input)
clean, err = util.SanitizeSVG(input)
}
if err != nil { return err } Prevention
- Export icons without DOCTYPE/DTD references
- Resolve any named entities to literal characters before sanitizing
- Treat DOCTYPE with internal subsets as hostile input (XXE risk)
- Add a lint rule that fails CI when icon assets contain '<!DOCTYPE'
When it happens
Trigger: DOCTYPE with an internal subset: '<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>'; a DOCTYPE naming a root other than svg; any other <!...> directive token; referencing external DTDs.
Common situations: SVGs copied from document-generation pipelines (Word, Inkscape with DTD output) that carry DOCTYPE declarations; legacy icon sets authored against SVG 1.1 DTD validation; malicious uploads attempting XXE.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- root element is not svg
- svg contains text outside the root element
- parse svg failed: %w
- svg contains too many tokens
- svg nesting depth exceeds %d
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/a2abd04c6598a210.
Report an issue: GitHub.