flipped-aurora/gin-vue-admin · error
文件名不合法
Error message
文件名不合法
What it means
readSkillFile validates the skill name and file name before joining them into a path under the skill directory. It returns 文件名不合法 when isSafeFileName(fileName) fails, i.e. the file name is blank after trimming, contains '..', contains '/' or '\\', or is not equal to its own filepath.Base. This guards against path traversal when reading skill scripts/resources/references/templates.
Source
Thrown at server/service/system/sys_skills.go:590
}
return "", "", fmt.Errorf("%s已存在", label)
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return "", "", err
}
content := defaultContent
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
return "", "", err
}
return cleanName, content, nil
}
func (s *SkillsService) readSkillFile(tool, skill, subDir, fileName string) (string, error) {
if !isSafeName(skill) {
return "", errors.New("技能名称不合法")
}
if !isSafeFileName(fileName) {
return "", errors.New("文件名不合法")
}
skillDir, err := s.skillDir(tool, skill)
if err != nil {
return "", err
}
filePath := filepath.Join(skillDir, subDir, fileName)
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
return string(content), nil
}
func (s *SkillsService) writeSkillFile(tool, skill, subDir, fileName, content string) error {
if !isSafeName(skill) {
return errors.New("技能名称不合法")
}
if !isSafeFileName(fileName) {View on GitHub (pinned to 3136500ef3)
Solutions
- Pass only the bare base file name (no directories, no '..') as fileName.
- Trim and validate the file name client-side before calling the API; reject empty or path-containing values.
- If a nested file is intended, the API must be extended — readSkillFile only supports files directly in subDir.
- Check that the name was not URL-encoded with %2F (%2e%2e is also rejected by the '..' check).
Example fix
// before svc.GetScript(tool, skill, "scripts", "../other/tool.py") // after svc.GetScript(tool, skill, "scripts", "tool.py")
Defensive patterns
Strategy: validation
Validate before calling
func safeFileName(s string) bool {
t := strings.TrimSpace(s)
return t != "" && !strings.Contains(t, "..") &&
!strings.ContainsAny(t, "/\\") && t == filepath.Base(t)
}
if !safeFileName(fileName) { return fmt.Errorf("invalid file name %q", fileName) } Type guard
func isBareFileName(s string) bool { return s != "" && s == filepath.Base(s) && !strings.ContainsAny(s, "\\/") && !strings.Contains(s, "..") } Try / catch
name, err := svc.GetScript(tool, skill, subDir, fileName)
if err != nil {
if strings.Contains(err.Error(), "文件名不合法") {
// sanitize: keep only filepath.Base, retry once
fileName = filepath.Base(fileName)
name, err = svc.GetScript(tool, skill, subDir, fileName)
}
if err != nil { return err }
} Prevention
- Always pass filepath.Base(path) of any client-side path.
- Validate names with the same rules the server uses (no '..', no separators).
- Never build file names by string concatenation of user input and paths.
- Log the raw input when this error occurs to spot encoding issues (%2F).
When it happens
Trigger: Calling GetScript, GetResource, GetReference or GetTemplate with a fileName that is empty/whitespace, includes a subdirectory path (e.g. 'sub/file.py'), contains '..' (e.g. '../../etc/passwd'), or uses backslashes on Linux.
Common situations: Frontend passes a stored relative path including folders instead of the bare file name; user-supplied input contains path separators; attempts to read files outside the skill dir; empty fileName after a string split on '/'.
Related errors
- 非法的key
- 参数错误:executionPlan 必须提供
- packageName 不能为空
- packageType 必须是 'package' 或 'plugin'
- packageType 和 packageInfo.template 必须保持一致
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/3d725b83d67690cb.
Report an issue: GitHub.