rules:
  - id: auth.go.oauth.hardcoded-client-secret
    languages:
      - go
    severity: ERROR
    message: |
      An `oauth2.Config` is built with a hardcoded string-literal
      `ClientSecret`. The client secret authenticates your application to the
      authorization server; committed to source control it is one search away
      from compromise, letting an attacker impersonate your client and redeem
      authorization codes for tokens (CWE-798). LLMs routinely inline the secret
      to make an OAuth sample runnable.

      Load it from the environment or a secret manager instead:
        conf := &oauth2.Config{
          ClientID:     os.Getenv("OAUTH_CLIENT_ID"),
          ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"),
        }
      Rotate any secret already committed.
    # Only a `ClientSecret:` set to a string LITERAL in an `oauth2.Config`
    # composite literal fires. `os.Getenv(...)` / a variable are not literals
    # and are structurally excluded. A regex allow-list drops obvious
    # placeholders / `${ENV}` templates and empty strings.
    patterns:
      - pattern: 'oauth2.Config{..., ClientSecret: "...", ...}'
      - pattern-not-regex: |-
          (?i)ClientSecret:\s*["']\s*["']
      - pattern-not-regex: |-
          (?i)ClientSecret:\s*["']\$\{?[A-Za-z_]+\}?["']
      - pattern-not-regex: |-
          (?i)ClientSecret:\s*["'](?:your[-_]|example|placeholder|xxx+|todo|changeme|change[-_]?me|replace|client[-_]?secret|<)
    metadata:
      oauthlint-rule-id: AUTH-GO-OAUTH-005
      oauthlint-doc-url: https://oauthlint.dev/rules/go-oauth-hardcoded-client-secret
      category: security
      cwe: CWE-798
      owasp: API2:2023
      llm-prevalence: MEDIUM
      technology:
        - oauth2
      references:
        - https://pkg.go.dev/golang.org/x/oauth2#Config
        - https://cwe.mitre.org/data/definitions/798.html
