flipped-aurora/gin-vue-admin · warning
非法的key
Error message
非法的key
What it means
This validation error is returned by the internal localPath helper when the key contains path-traversal sequences ('..') or characters illegal in file names (\ / : * ? " < > |). It is a security guard preventing callers from addressing files outside the configured local store path.
Source
Thrown at server/utils/upload/local.go:115
err = os.Remove(p)
if err != nil {
return errors.New("文件删除失败: " + err.Error())
}
return nil
}
// localPath 校验 key 并拼接出本地存储的绝对路径,复用 DeleteFile 中的路径穿越防护逻辑。
func (*Local) localPath(ctx context.Context, key string) (string, error) {
// 检查 key 是否为空
if key == "" {
return "", errors.New("key不能为空")
}
// 验证 key 是否包含非法字符或尝试访问存储路径之外的文件
if strings.Contains(key, "..") || strings.ContainsAny(key, `\/:*?"<>|`) {
return "", errors.New("非法的key")
}
return filepath.Join(global.GVA_CONFIG.Local.StorePath, key), nil
}
// Exists 检查本地文件是否存在,"不存在"统一降级为 (false, nil)。
func (l *Local) Exists(ctx context.Context, key string) (bool, error) {
p, err := l.localPath(ctx, key)
if err != nil {
return false, err
}
info, err := os.Stat(p)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
logger.WithCtx(ctx).Mod("upload").Err(err).Error("function os.Stat() failed")View on GitHub (pinned to 3136500ef3)
Solutions
- Pass the bare filename key exactly as returned by UploadFile (flat, slash-free filename), not a path or a foreign backend's object key.
- Sanitize/normalize keys at ingestion: strip directories and reject illegal characters before persisting them.
- If you must support hierarchical keys, extend localPath to safely join and re-verify the result stays within StorePath (filepath.Clean + prefix check) instead of blanket rejection.
- Never construct keys from raw user input; derive them from the stored record's filename field produced by UploadFile.
Example fix
// before key := objectURL // "https://cdn/x/a.png" or "sub/dir/a.png" from MinIO local.DeleteFile(ctx, key) // 非法的key // after key := filepath.Base(strings.ReplaceAll(objectURL, "\\", "/")) // "a.png" local.DeleteFile(ctx, key)
Defensive patterns
Strategy: validation
Validate before calling
func isSafeLocalKey(key string) bool {
if strings.TrimSpace(key) == "" {
return false
}
if strings.Contains(key, "..") || strings.ContainsAny(key, `\/:*?"<>|`) {
return false
}
return true
}
// usage: if !isSafeLocalKey(key) { return errors.New("invalid key") } Type guard
type SafeKey string
func newSafeKey(raw string) (SafeKey, bool) {
if strings.Contains(raw, "..") || strings.ContainsAny(raw, `\/:*?"<>|`) {
return "", false
}
return SafeKey(raw), true
} Try / catch
err := local.DeleteFile(ctx, key)
if err != nil && err.Error() == "非法的key" {
return fmt.Errorf("key %q is not a local storage key (slashes/illegal chars)", key)
} Prevention
- Store the flat filename returned by UploadFile as the canonical key and delete by that.
- Never pass foreign backend keys (S3/MinIO paths) directly to the local adapter.
- Sanitize user-supplied filenames with filepath.Base at ingestion time.
- Treat this error as a security signal — log the rejected key and investigate its origin.
When it happens
Trigger: Calling DeleteFile or Exists with a key such as "../secret.txt", "a/b.png", or any key containing backslashes or Windows-reserved characters — usually keys produced by another storage backend (e.g. MinIO/S3 keys with slashes) being passed to the local adapter.
Common situations: Mixing storage backends: S3/MinIO object keys use '/' separators and are rejected by the local adapter; user-supplied filenames reaching the delete path unsanitized; attacker-crafted keys probing for path traversal.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/b1dbc37c25dafcdf.
Report an issue: GitHub.