build: 取消 gosec G703/G704 全局排除,生产代码逐点 nolint、测试文件按路径豁免;DEV_GUIDE 同步 golangci-lint v2.13

This commit is contained in:
feeeei
2026-08-24 12:21:06 +08:00
parent 3b81776429
commit 73aabc861c
5 changed files with 19 additions and 13 deletions
+3 -3
View File
@@ -34,8 +34,8 @@
### 开发工具 ### 开发工具
```bash ```bash
# golangci-lint(CI 用 v2.9,本地建议装同一版以免版本差异带来的噪音) # golangci-lint(CI 用 v2.13,本地建议装同一版以免版本差异带来的噪音)
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.9 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.13
# pnpm (前端包管理) # pnpm (前端包管理)
npm install -g pnpm npm install -g pnpm
@@ -47,7 +47,7 @@ npm install -g pnpm
| Workflow | 触发条件 | 检查内容 | | Workflow | 触发条件 | 检查内容 |
|----------|----------|----------| |----------|----------|----------|
| **backend-ci.yml** | push, pull_request | 单元测试 + 集成测试 + golangci-lint v2.9 | | **backend-ci.yml** | push, pull_request | 单元测试 + 集成测试 + golangci-lint v2.13 |
| **security-scan.yml** | push, pull_request, 每周一 | govulncheck + gosec + pnpm audit | | **security-scan.yml** | push, pull_request, 每周一 | govulncheck + gosec + pnpm audit |
| **release.yml** | tag `v*` | 构建发布(PR 不触发) | | **release.yml** | tag `v*` | 构建发布(PR 不触发) |
+10 -4
View File
@@ -57,10 +57,6 @@ linters:
- G304 - G304
- G306 - G306
- G404 - G404
# G703/G704 是 G304/G107 的污点分析版:网关本职就是按配置转发到上游 URL、按配置写本地文件,
# 污点来源即配置本身,规则不适用。
- G703
- G704
severity: high severity: high
confidence: high confidence: high
errcheck: errcheck:
@@ -125,6 +121,16 @@ linters:
# Default: true — must be true, ent generates 130K+ lines of code # Default: true — must be true, ent generates 130K+ lines of code
generated-is-used: true generated-is-used: true
exclusions:
rules:
# G703/G704 污点分析在测试文件中只会命中 httptest mock 与测试者自设的
# 环境变量路径,不构成攻击面;且该分析跨环境结果不稳定(本地/CI 报告的
# 位置集合不同),逐点 nolint 无法收敛,故按路径豁免。生产代码不豁免,
# 必须逐点 //nolint:gosec 并写明信任边界。
- path: '_test\.go$'
linters: [ gosec ]
text: 'G70[34]'
formatters: formatters:
enable: enable:
- gofmt - gofmt
+2 -2
View File
@@ -53,10 +53,10 @@ func Do(client *http.Client, req *http.Request) (*http.Response, error) {
client = http.DefaultClient client = http.DefaultClient
} }
if req == nil || !Active(req.Context()) { if req == nil || !Active(req.Context()) {
return client.Do(req) return client.Do(req) //nolint:gosec // G704: 通用埋点包装器,不构造 URL;请求由调用方构造,SSRF 信任边界在调用方
} }
startedAt := time.Now() startedAt := time.Now()
response, err := client.Do(req) response, err := client.Do(req) //nolint:gosec // G704: 同上
RecordDependency(req.Context(), dependencyModule(req), startedAt, time.Now()) RecordDependency(req.Context(), dependencyModule(req), startedAt, time.Now())
return response, err return response, err
} }
+3 -3
View File
@@ -1520,19 +1520,19 @@ func (s *GatewayService) initDebugGatewayBodyFile(path string) {
} }
// 如果 path 指向一个已存在的目录,自动追加默认文件名 // 如果 path 指向一个已存在的目录,自动追加默认文件名
if info, err := os.Stat(path); err == nil && info.IsDir() { if info, err := os.Stat(path); err == nil && info.IsDir() { //nolint:gosec // G703: path 仅来自启动环境变量 SUB2API_DEBUG_GATEWAY_BODY(运维配置),非请求输入
path = filepath.Join(path, debugGatewayBodyDefaultFilename) path = filepath.Join(path, debugGatewayBodyDefaultFilename)
} }
// 确保父目录存在 // 确保父目录存在
if dir := filepath.Dir(path); dir != "." { if dir := filepath.Dir(path); dir != "." {
if err := os.MkdirAll(dir, 0755); err != nil { if err := os.MkdirAll(dir, 0755); err != nil { //nolint:gosec // G703: 同上
slog.Error("failed to create gateway debug log directory", "dir", dir, "error", err) slog.Error("failed to create gateway debug log directory", "dir", dir, "error", err)
return return
} }
} }
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) //nolint:gosec // G703: 同上
if err != nil { if err != nil {
slog.Error("failed to open gateway debug log file", "path", path, "error", err) slog.Error("failed to open gateway debug log file", "path", path, "error", err)
return return
+1 -1
View File
@@ -596,7 +596,7 @@ func (s *PricingService) useFallbackPricing() error {
} }
pricingFile := s.getPricingFilePath() pricingFile := s.getPricingFilePath()
if err := os.WriteFile(pricingFile, data, 0644); err != nil { if err := os.WriteFile(pricingFile, data, 0644); err != nil { //nolint:gosec // G703: 路径为配置的数据目录 + 硬编码文件名,非请求输入
logger.LegacyPrintf("service.pricing", "[Pricing] Failed to copy fallback: %v", err) logger.LegacyPrintf("service.pricing", "[Pricing] Failed to copy fallback: %v", err)
} }