Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
A static state provides ZERO CSRF protection: the whole point is an unguessable, per-request value that you store and then compare on the callback. A literal that ships in your source is known to everyone and identical on every request, so an attacker can forge a matching callback.
Generate state fresh per request from a CSPRNG (e.g. crypto/rand -> base64.URLEncoding.EncodeToString(b)), persist it in the session/cookie, and verify it when the provider redirects back. With golang.org/x/oauth2, pass that random value as the first argument to Config.AuthCodeURL(state, ...).
VULNERABLE
vulnerable.go
package mainimport ( "golang.org/x/oauth2")// Hardcoded state passed to AuthCodeURL — constant on every request.func authorizeStatic(conf *oauth2.Config) string { // ruleid: auth.go.oauth.static-state return conf.AuthCodeURL("xyz123")}// Hardcoded state alongside extra AuthCodeOption arguments.func authorizeStaticWithOpts(conf *oauth2.Config) string { // ruleid: auth.go.oauth.static-state return conf.AuthCodeURL("state-token", oauth2.AccessTypeOffline)}func main() {}
SAFE
safe.go
package mainimport ( "crypto/rand" "encoding/base64" "golang.org/x/oauth2")// randomState returns a fresh CSPRNG-backed state value.func randomState() string { b := make([]byte, 32) _, _ = rand.Read(b) return base64.URLEncoding.EncodeToString(b)}// Safe: a per-request random state generated from crypto/rand.func authorizeRandom(conf *oauth2.Config) string { state := randomState() // ok: auth.go.oauth.static-state return conf.AuthCodeURL(state, oauth2.AccessTypeOffline)}// Safe trap: the empty-string form is a missing state (covered elsewhere),// not a hardcoded literal, and must not be flagged by this rule.func authorizeEmpty(conf *oauth2.Config) string { // ok: auth.go.oauth.static-state return conf.AuthCodeURL("")}func main() {}
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.