- #9 CDN 本地化:marked/DOMPurify/highlight.js/cropperjs/easymde 入 static/vendor(go:embed),Tailwind 改静态构建(scripts/build_tailwind.sh),CSP 收紧为 default-src 'self' - #10 登录限速:IP+用户名维度 5 次失败锁 15 分钟,内存实现有界(handlers/login_ratelimit.go) - #25 计时侧信道:用户不存在时执行 dummy bcrypt 抹平时间差(随 #10 实施) - #11 配置文件权限 0640 - #12 首启随机一次性密码(弃用 admin/admin) - #13 unix socket 660 + 代理用户加组提示 - #22 storage_dir 路径穿越校验(单安全路径段) - #23 密码最小长度统一(改密/建号/重置),#24 邮箱格式统一校验 - 新增 13 个单元测试;go test ./... 含 -race 全绿
23 lines
537 B
Go
23 lines
537 B
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// TestConfigFileCreatedNotWorldReadable covers SECURITY_TODO #11: the config
|
|
// file (which embeds the session secret) must not be group/world readable.
|
|
func TestConfigFileCreatedNotWorldReadable(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "config.yaml")
|
|
LoadConfig(path)
|
|
|
|
st, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Fatalf("config file not created: %v", err)
|
|
}
|
|
if perm := st.Mode().Perm(); perm != 0640 {
|
|
t.Fatalf("config perms = %v, want 0640", perm)
|
|
}
|
|
}
|