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

  1. Delete the DOCTYPE declaration entirely — it is optional and never needed for rendering
  2. If DTD validation metadata matters, keep it in a separate file and ship only the bare <svg> markup
  3. For batch processing, strip directives with a regex on '<!DOCTYPE' ... '>' before calling SanitizeSVG
  4. 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

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


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/a2abd04c6598a210. Report an issue: GitHub.