From 8ba937ec4a41d373791d2251586179426d29de26 Mon Sep 17 00:00:00 2001 From: yusing Date: Sun, 22 Feb 2026 16:05:02 +0800 Subject: [PATCH] refactor(middleware): replace sensitive fields with redacted types --- .../net/gphttp/middleware/captcha/hcaptcha.go | 11 ++++++----- internal/net/gphttp/middleware/crowdsec.go | 15 ++++++++------- internal/net/gphttp/middleware/oidc.go | 15 ++++++++------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/internal/net/gphttp/middleware/captcha/hcaptcha.go b/internal/net/gphttp/middleware/captcha/hcaptcha.go index f3be9ef3..4a6cf9ab 100644 --- a/internal/net/gphttp/middleware/captcha/hcaptcha.go +++ b/internal/net/gphttp/middleware/captcha/hcaptcha.go @@ -13,13 +13,14 @@ import ( "github.com/bytedance/sonic" gperr "github.com/yusing/goutils/errs" + strutils "github.com/yusing/goutils/strings" ) type HcaptchaProvider struct { ProviderBase - SiteKey string `json:"site_key" validate:"required"` - Secret string `json:"secret" validate:"required"` + SiteKey strutils.Redacted `json:"site_key" validate:"required"` + Secret strutils.Redacted `json:"secret" validate:"required"` } // CSPDirectives returns the CSP directives for the Hcaptcha provider. @@ -51,10 +52,10 @@ func (p *HcaptchaProvider) Verify(r *http.Request) error { ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second) defer cancel() formData := url.Values{} - formData.Set("secret", p.Secret) + formData.Set("secret", p.Secret.String()) formData.Set("response", response) formData.Set("remoteip", remoteIP) - formData.Set("sitekey", p.SiteKey) + formData.Set("sitekey", p.SiteKey.String()) req, err := http.NewRequestWithContext(ctx, http.MethodPost, "https://api.hcaptcha.com/siteverify", bytes.NewBufferString(formData.Encode())) if err != nil { @@ -92,7 +93,7 @@ func (p *HcaptchaProvider) FormHTML() string { return `
` } diff --git a/internal/net/gphttp/middleware/crowdsec.go b/internal/net/gphttp/middleware/crowdsec.go index 9540deb6..078f51f5 100644 --- a/internal/net/gphttp/middleware/crowdsec.go +++ b/internal/net/gphttp/middleware/crowdsec.go @@ -15,6 +15,7 @@ import ( entrypoint "github.com/yusing/godoxy/internal/entrypoint/types" httputils "github.com/yusing/goutils/http" ioutils "github.com/yusing/goutils/io" + strutils "github.com/yusing/goutils/strings" ) type ( @@ -23,12 +24,12 @@ type ( } CrowdsecMiddlewareOpts struct { - Route string `json:"route" validate:"required"` // route name (alias) or IP address - Port int `json:"port"` // port number (optional if using route name) - APIKey string `json:"api_key" validate:"required"` // API key for CrowdSec AppSec (mandatory) - Endpoint string `json:"endpoint"` // default: "/" - LogBlocked bool `json:"log_blocked"` // default: false - Timeout time.Duration `json:"timeout"` // default: 5 seconds + Route string `json:"route" validate:"required"` // route name (alias) or IP address + Port int `json:"port"` // port number (optional if using route name) + APIKey strutils.Redacted `json:"api_key" validate:"required"` // API key for CrowdSec AppSec (mandatory) + Endpoint string `json:"endpoint"` // default: "/" + LogBlocked bool `json:"log_blocked"` // default: false + Timeout time.Duration `json:"timeout"` // default: 5 seconds httpClient *http.Client } @@ -119,7 +120,7 @@ func (m *crowdsecMiddleware) before(w http.ResponseWriter, r *http.Request) (pro req.Header.Set("X-Crowdsec-Appsec-Uri", r.URL.RequestURI()) req.Header.Set("X-Crowdsec-Appsec-Host", r.Host) req.Header.Set("X-Crowdsec-Appsec-Verb", r.Method) - req.Header.Set("X-Crowdsec-Appsec-Api-Key", m.APIKey) + req.Header.Set("X-Crowdsec-Appsec-Api-Key", m.APIKey.String()) req.Header.Set("X-Crowdsec-Appsec-User-Agent", r.UserAgent()) req.Header.Set("X-Crowdsec-Appsec-Http-Version", httpVersion) diff --git a/internal/net/gphttp/middleware/oidc.go b/internal/net/gphttp/middleware/oidc.go index e9e35509..78e21978 100644 --- a/internal/net/gphttp/middleware/oidc.go +++ b/internal/net/gphttp/middleware/oidc.go @@ -11,14 +11,15 @@ import ( "github.com/yusing/godoxy/internal/auth" httpevents "github.com/yusing/goutils/events/http" "github.com/yusing/goutils/http/httpheaders" + strutils "github.com/yusing/goutils/strings" ) type oidcMiddleware struct { - AllowedUsers []string `json:"allowed_users"` - AllowedGroups []string `json:"allowed_groups"` - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - Scopes string `json:"scopes"` + AllowedUsers []string `json:"allowed_users"` + AllowedGroups []string `json:"allowed_groups"` + ClientID strutils.Redacted `json:"client_id"` + ClientSecret strutils.Redacted `json:"client_secret"` + Scopes string `json:"scopes"` auth *auth.OIDCProvider @@ -70,8 +71,8 @@ func (amw *oidcMiddleware) initSlow() error { // Use custom client credentials customProvider, err := auth.NewOIDCProviderWithCustomClient( authProvider, - amw.ClientID, - amw.ClientSecret, + amw.ClientID.String(), + amw.ClientSecret.String(), ) if err != nil { return err