fix: 修复代码审核发现的安全和质量问题
安全修复(P0): - 移除硬编码的 OAuth client_secret(Antigravity、Gemini CLI), 改为通过环境变量注入(ANTIGRAVITY_OAUTH_CLIENT_SECRET、 GEMINI_CLI_OAUTH_CLIENT_SECRET) - 新增 logredact.RedactText() 对非结构化文本做敏感信息脱敏, 覆盖 GOCSPX-*/AIza* 令牌和常见 key=value 模式 - 日志中不再打印 org_uuid、account_uuid、email_address 等敏感值 安全修复(P1): - URL 验证增强:新增 ValidateHTTPURL 统一入口,支持 allowlist 和 私网地址阻断(localhost/内网 IP) - 代理回退安全:代理初始化失败时默认阻止直连回退,防止 IP 泄露, 可通过 security.proxy_fallback.allow_direct_on_error 显式开启 - Gemini OAuth 配置校验:client_id 与 client_secret 必须同时 设置或同时留空 其他改进: - 新增 tools/secret_scan.py 密钥扫描工具和 Makefile secret-scan 目标 - 更新所有 docker-compose 和部署配置,传递 OAuth secret 环境变量 - google_one OAuth 类型使用固定 redirectURI,与 code_assist 对齐 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -176,6 +176,7 @@ type SecurityConfig struct {
|
||||
URLAllowlist URLAllowlistConfig `mapstructure:"url_allowlist"`
|
||||
ResponseHeaders ResponseHeaderConfig `mapstructure:"response_headers"`
|
||||
CSP CSPConfig `mapstructure:"csp"`
|
||||
ProxyFallback ProxyFallbackConfig `mapstructure:"proxy_fallback"`
|
||||
ProxyProbe ProxyProbeConfig `mapstructure:"proxy_probe"`
|
||||
}
|
||||
|
||||
@@ -200,6 +201,12 @@ type CSPConfig struct {
|
||||
Policy string `mapstructure:"policy"`
|
||||
}
|
||||
|
||||
type ProxyFallbackConfig struct {
|
||||
// AllowDirectOnError 当代理初始化失败时是否允许回退直连。
|
||||
// 默认 false:避免因代理配置错误导致 IP 泄露/关联。
|
||||
AllowDirectOnError bool `mapstructure:"allow_direct_on_error"`
|
||||
}
|
||||
|
||||
type ProxyProbeConfig struct {
|
||||
InsecureSkipVerify bool `mapstructure:"insecure_skip_verify"` // 已禁用:禁止跳过 TLS 证书验证
|
||||
}
|
||||
@@ -1047,9 +1054,20 @@ func setDefaults() {
|
||||
viper.SetDefault("gemini.oauth.scopes", "")
|
||||
viper.SetDefault("gemini.quota.policy", "")
|
||||
|
||||
// Security - proxy fallback
|
||||
viper.SetDefault("security.proxy_fallback.allow_direct_on_error", false)
|
||||
|
||||
}
|
||||
|
||||
func (c *Config) Validate() error {
|
||||
// Gemini OAuth 配置校验:client_id 与 client_secret 必须同时设置或同时留空。
|
||||
// 留空时表示使用内置的 Gemini CLI OAuth 客户端(其 client_secret 通过环境变量注入)。
|
||||
geminiClientID := strings.TrimSpace(c.Gemini.OAuth.ClientID)
|
||||
geminiClientSecret := strings.TrimSpace(c.Gemini.OAuth.ClientSecret)
|
||||
if (geminiClientID == "") != (geminiClientSecret == "") {
|
||||
return fmt.Errorf("gemini.oauth.client_id and gemini.oauth.client_secret must be both set or both empty")
|
||||
}
|
||||
|
||||
if strings.TrimSpace(c.Server.FrontendURL) != "" {
|
||||
if err := ValidateAbsoluteHTTPURL(c.Server.FrontendURL); err != nil {
|
||||
return fmt.Errorf("server.frontend_url invalid: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user