siyuan-note/siyuan · error
invalid custom emoji name
Error message
invalid custom emoji name
What it means
First throw of 'invalid custom emoji name' in normalizeCustomEmojiPath's loop. After TrimSpace, a path segment is empty, '.', or '..'. This catches empty segments (leading/trailing/double slash), current-directory, and parent-directory references — i.e. path traversal or malformed names supplied via the name form field.
Source
Thrown at kernel/api/system.go:402
return nil, "", fmt.Errorf("unsupported custom emoji image format")
}
func normalizeCustomEmojiPath(name, ext string) (string, error) {
name = strings.TrimSpace(strings.ReplaceAll(name, "\\", "/"))
parts := strings.Split(name, "/")
if len(parts) == 0 {
return "", fmt.Errorf("custom emoji name must not be empty")
}
lastIndex := len(parts) - 1
switch strings.ToLower(filepath.Ext(parts[lastIndex])) {
case ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg":
parts[lastIndex] = strings.TrimSuffix(parts[lastIndex], filepath.Ext(parts[lastIndex]))
}
for i, part := range parts {
part = strings.TrimSpace(part)
if part == "" || part == "." || part == ".." {
return "", fmt.Errorf("invalid custom emoji name")
}
part = util.FilterUploadFileName(part)
if part == "" || part == "." || part == ".." {
return "", fmt.Errorf("invalid custom emoji name")
}
parts[i] = part
}
parts[lastIndex] += ext
return strings.Join(parts, "/"), nil
}
func checkUpdate(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
returnView on GitHub (pinned to 251596fc0d)
Solutions
- Provide a simple non-empty basename without slashes, e.g. "myemoji" or "group/icon".
- Strip leading/trailing slashes and collapse repeated slashes before submitting.
- Never send '.' or '..' segments; they are rejected to prevent escaping the emojis directory.
Example fix
// before
c.PostForm("name") == "../etc/passwd" // -> invalid custom emoji name
// after: submit a flat, sanitized name
name := "myemoji" // or "packs/happy" for a subfolder
// client side:
// name = name.trim().replace(/\/+/g, '/').replace(/^\/+|\/+$/g, '') Defensive patterns
Strategy: validation
Validate before calling
// Reject path-traversal / empty segments before submitting the name
name = strings.TrimSpace(strings.ReplaceAll(name, "\\", "/"))
for _, part := range strings.Split(name, "/") {
part = strings.TrimSpace(part)
if part == "" || part == "." || part == ".." {
return errors.New("name contains an empty or traversal segment")
}
} Prevention
- Send a flat basename or a clean relative path with no leading/trailing slashes.
- Never include '.' or '..' segments.
- Collapse repeated slashes client-side before submit.
When it happens
Trigger: POST /api/system/addCustomEmoji with name like "", "/icon", "a//b", "../icon", "./x", or "." — any segment that is empty or a dot/dotdot after trimming. A trailing slash or a path-traversal attempt lands here.
Common situations: Client sends name with a trailing slash; user types a relative path hoping to write outside the emojis dir; front-end bug submits an empty name when the field is left blank.
Related errors
- custom emoji file is too large
- custom emoji file must not be empty
- invalid custom emoji image
- unsupported custom emoji image format
- custom emoji name must not be empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/7067ce79e9162b50.
Report an issue: GitHub.