FileCodeBox Go 重写版 v2.5.6(安全审计修复版)

Go 1.27.1 (Gin+GORM) + Vue 3 文件快传服务:

- 安全审计全部修复(docs/security-audit-2026-09-05.md):
  bcrypt 密码哈希与自动升级、presign 直传服务端大小/内容校验、
  全局请求体上限、依赖升级(govulncheck 0 命中)、janitor 后台清理、
  管理端审计动作落库、/admin CORS 收紧、通知内容白名单净化、
  会话默认 7 天、限流缓存故障降级、robots.txt 端点等
- 前端:取件链接复制修复(不再重复拼接提取码)、markdown 净化器加固
- Redis 支持库号(FCB_REDIS_DB / redis://…/db URL)
- 文档:docs/api/* 与 openapi.yaml 同步最新行为(robots.txt、
  提码 5 位起、chunk 32MiB 上限、admin 审计动作等)

验证:gofmt/go vet/go test 全绿;二进制端到端冒烟通过
This commit is contained in:
2026-09-05 04:22:41 +08:00
commit 9686fe887a
173 changed files with 32455 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
package storage
import (
"crypto/sha256"
"encoding/hex"
"io"
"testing"
)
// TestSanitizePath 校验路径穿越防护。
func TestSanitizePath(t *testing.T) {
cases := []struct {
in string
ok bool
out string
}{
{"2025/08/uuid.zip", true, "2025/08/uuid.zip"},
{"/2025/08/uuid.zip", true, "2025/08/uuid.zip"},
{"a\\b\\c.txt", true, "a/b/c.txt"},
{"../etc/passwd", false, ""},
{"a/../../b", false, ""},
{"..", false, ""},
{"", false, ""},
}
for _, tc := range cases {
got, ok := SanitizePath(tc.in)
if ok != tc.ok || (ok && got != tc.out) {
t.Errorf("SanitizePath(%q) = (%q, %v), want (%q, %v)", tc.in, got, ok, tc.out, tc.ok)
}
}
}
// TestSanitizeFileName 校验文件名清理。
func TestSanitizeFileName(t *testing.T) {
cases := []struct{ in, want string }{
{"hello world.zip", "hello_world.zip"},
{"/path/to/file.txt", "file.txt"},
{"a<b>:c?.mp4", "a_b_c_.mp4"}, // 连续下划线压缩,对齐参考 re.sub(r"_+", "_")
{"", "unnamed_file"},
{"__..__", "unnamed_file"},
}
for _, tc := range cases {
if got := SanitizeFileName(tc.in); got != tc.want {
t.Errorf("SanitizeFileName(%q) = %q, want %q", tc.in, got, tc.want)
}
}
}
// TestChunkPartPath 校验分片路径约定。
func TestChunkPartPath(t *testing.T) {
got := ChunkPartPath("2025/08/uuid.zip", "upload-1", 3)
want := "2025/08/chunks/upload-1/3.part"
if got != want {
t.Errorf("ChunkPartPath = %q, want %q", got, want)
}
}
// TestChunkDir 校验分片目录约定。
func TestChunkDir(t *testing.T) {
got := ChunkDir("2025/08/uuid.zip", "upload-1")
want := "2025/08/chunks/upload-1/uuid.zip"
if got != want {
t.Errorf("ChunkDir = %q, want %q", got, want)
}
}
// TestSHA256Helper 辅助:确认 sha256 用法一致(合并校验依赖)。
func TestSHA256Helper(t *testing.T) {
h := sha256.Sum256([]byte("abc"))
if got := hex.EncodeToString(h[:]); got != "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" {
t.Errorf("sha256(abc) = %s", got)
}
_ = io.EOF
}