Search

Find a vulnerability

Search criteria

    Related vulnerabilities

    GHSA-W6J9-VW59-27WV

    Vulnerability from github – Published: 2026-06-22 17:09 – Updated: 2026-06-22 17:09
    VLAI
    Summary
    Gogs has an Authentication Bypass via Unvalidated Reverse Proxy Headers
    Details

    Summary

    When ENABLE_REVERSE_PROXY_AUTHENTICATION is enabled, Gogs accepts the configured authentication header (default: X-WEBAUTH-USER) directly from client requests without validating that the request originated from a trusted reverse proxy. Any remote attacker who can reach the Gogs service can forge this header to impersonate any user or trigger automatic account creation, completely bypassing authentication.

    Root Cause

    The vulnerability exists because Gogs reads the authentication header directly from the incoming HTTP request without any verification that the header was set by a trusted reverse proxy.

    Vulnerable Code Flow

    In internal/context/auth.go lines 206-234:

    func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store) (_ *database.User, isBasicAuth, isTokenAuth bool) {
        // ... existing auth checks ...
    
        if uid <= 0 {
            if conf.Auth.EnableReverseProxyAuthentication {
                // Reads header DIRECTLY from client request - NO VALIDATION!
                webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader)
                if len(webAuthUser) > 0 {
                    user, err := store.GetUserByUsername(ctx.Req.Context(), webAuthUser)
                    if err != nil {
                        if !database.IsErrUserNotExist(err) {
                            log.Error("Failed to get user by name: %v", err)
                            return nil, false, false
                        }
    
                        // Check if enabled auto-registration.
                        if conf.Auth.EnableReverseProxyAutoRegistration {
                            // Creates new user with forged username!
                            user, err = store.CreateUser(
                                ctx.Req.Context(),
                                webAuthUser,
                                gouuid.NewV4().String()+"@localhost",
                                database.CreateUserOptions{
                                    Activated: true,
                                },
                            )
                            if err != nil {
                                log.Error("Failed to create user %q: %v", webAuthUser, err)
                                return nil, false, false
                            }
                        }
                    }
                    // Returns user as authenticated without any verification!
                    return user, false, false
                }
            }
            // ... fallback to basic auth ...
        }
        // ...
    }
    

    The code has zero validation that: 1. The request came through a reverse proxy 2. The header was set by the proxy (not the client) 3. Gogs is actually behind a reverse proxy 4. The direct access to Gogs is restricted

    The vulnerability occurs when: - Gogs is publicly accessible (e.g., 0.0.0.0:3000) - ENABLE_REVERSE_PROXY_AUTHENTICATION = true

    Proof of Concept

    Prerequisites

    Gogs instance with the following configuration in custom/conf/app.ini:

    [auth]
    ENABLE_REVERSE_PROXY_AUTHENTICATION = true
    

    An attacker can impersonate any user including administrators:

    # Become admin instantly
    curl http://gogs.example.com/ -H "X-WEBAUTH-USER: <username>"
    

    impersonation_example

    Recommended Fixes

    Add validation to ensure headers come from trusted sources:

    func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store) (_ *database.User, isBasicAuth, isTokenAuth bool) {
        // ... existing code ...
    
        if uid <= 0 {
            if conf.Auth.EnableReverseProxyAuthentication {
                // Validate request is from trusted proxy
                if !isRequestFromTrustedProxy(ctx.Req) {
                    log.Warn("Reverse proxy auth header received from untrusted source: %s", ctx.RemoteAddr())
                    return nil, false, false
                }
    
                webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader)
                // ... rest of the code ...
            }
        }
        // ...
    }
    
    // New validation function
    func isRequestFromTrustedProxy(req *http.Request) bool {
        // Check if request is from localhost/trusted IPs
        remoteIP := getRemoteIP(req)
    
        // Only accept from localhost by default
        if remoteIP.IsLoopback() {
            return true
        }
    
        // Check against configured trusted proxy IPs
        for _, trustedIP := range conf.Auth.TrustedProxyIPs {
            if remoteIP.String() == trustedIP {
                return true
            }
        }
    
        return false
    }
    

    Add configuration option:

    [auth]
    ENABLE_REVERSE_PROXY_AUTHENTICATION = false
    REVERSE_PROXY_AUTHENTICATION_HEADER = X-WEBAUTH-USER
    ; Comma-separated list of trusted proxy IPs (default: 127.0.0.1)
    TRUSTED_PROXY_IPS = 127.0.0.1,::1
    ; Whether to require trusted proxy validation (recommended: true)
    REQUIRE_TRUSTED_PROXY = true
    

    References

    Show details on source website

    {
      "affected": [
        {
          "database_specific": {
            "last_known_affected_version_range": "\u003c= 0.14.2"
          },
          "package": {
            "ecosystem": "Go",
            "name": "gogs.io/gogs"
          },
          "ranges": [
            {
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "0.14.3"
                }
              ],
              "type": "ECOSYSTEM"
            }
          ]
        }
      ],
      "aliases": [
        "CVE-2026-25119"
      ],
      "database_specific": {
        "cwe_ids": [
          "CWE-290"
        ],
        "github_reviewed": true,
        "github_reviewed_at": "2026-06-22T17:09:51Z",
        "nvd_published_at": null,
        "severity": "HIGH"
      },
      "details": "## Summary\n\nWhen `ENABLE_REVERSE_PROXY_AUTHENTICATION` is enabled, Gogs accepts the configured authentication header (default: `X-WEBAUTH-USER`) directly from client requests without validating that the request originated from a trusted reverse proxy. Any remote attacker who can reach the Gogs service can forge this header to impersonate any user or trigger automatic account creation, completely bypassing authentication.\n\n## Root Cause\n\nThe vulnerability exists because Gogs reads the authentication header directly from the incoming HTTP request without any verification that the header was set by a trusted reverse proxy.\n\n### Vulnerable Code Flow\n\nIn `internal/context/auth.go` lines 206-234:\n\n```go\nfunc authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store) (_ *database.User, isBasicAuth, isTokenAuth bool) {\n    // ... existing auth checks ...\n\n    if uid \u003c= 0 {\n        if conf.Auth.EnableReverseProxyAuthentication {\n            // Reads header DIRECTLY from client request - NO VALIDATION!\n            webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader)\n            if len(webAuthUser) \u003e 0 {\n                user, err := store.GetUserByUsername(ctx.Req.Context(), webAuthUser)\n                if err != nil {\n                    if !database.IsErrUserNotExist(err) {\n                        log.Error(\"Failed to get user by name: %v\", err)\n                        return nil, false, false\n                    }\n\n                    // Check if enabled auto-registration.\n                    if conf.Auth.EnableReverseProxyAutoRegistration {\n                        // Creates new user with forged username!\n                        user, err = store.CreateUser(\n                            ctx.Req.Context(),\n                            webAuthUser,\n                            gouuid.NewV4().String()+\"@localhost\",\n                            database.CreateUserOptions{\n                                Activated: true,\n                            },\n                        )\n                        if err != nil {\n                            log.Error(\"Failed to create user %q: %v\", webAuthUser, err)\n                            return nil, false, false\n                        }\n                    }\n                }\n                // Returns user as authenticated without any verification!\n                return user, false, false\n            }\n        }\n        // ... fallback to basic auth ...\n    }\n    // ...\n}\n```\n\nThe code has **zero validation** that:\n1. The request came through a reverse proxy\n2. The header was set by the proxy (not the client)\n3. Gogs is actually behind a reverse proxy\n4. The direct access to Gogs is restricted\n\nThe vulnerability occurs when:\n- Gogs is publicly accessible (e.g., `0.0.0.0:3000`)\n- `ENABLE_REVERSE_PROXY_AUTHENTICATION = true`\n\n## Proof of Concept\n\n### Prerequisites\n\nGogs instance with the following configuration in `custom/conf/app.ini`:\n\n```ini\n[auth]\nENABLE_REVERSE_PROXY_AUTHENTICATION = true\n```\n\nAn attacker can impersonate any user including administrators:\n\n```bash\n# Become admin instantly\ncurl http://gogs.example.com/ -H \"X-WEBAUTH-USER: \u003cusername\u003e\"\n```\n\n\u003cimg width=\"1835\" height=\"1143\" alt=\"impersonation_example\" src=\"https://github.com/user-attachments/assets/bae60772-5eb3-4f54-9fe0-5db01595bd56\" /\u003e\n\n## Recommended Fixes\n\nAdd validation to ensure headers come from trusted sources:\n\n```go\nfunc authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store) (_ *database.User, isBasicAuth, isTokenAuth bool) {\n    // ... existing code ...\n\n    if uid \u003c= 0 {\n        if conf.Auth.EnableReverseProxyAuthentication {\n            // Validate request is from trusted proxy\n            if !isRequestFromTrustedProxy(ctx.Req) {\n                log.Warn(\"Reverse proxy auth header received from untrusted source: %s\", ctx.RemoteAddr())\n                return nil, false, false\n            }\n\n            webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader)\n            // ... rest of the code ...\n        }\n    }\n    // ...\n}\n\n// New validation function\nfunc isRequestFromTrustedProxy(req *http.Request) bool {\n    // Check if request is from localhost/trusted IPs\n    remoteIP := getRemoteIP(req)\n\n    // Only accept from localhost by default\n    if remoteIP.IsLoopback() {\n        return true\n    }\n\n    // Check against configured trusted proxy IPs\n    for _, trustedIP := range conf.Auth.TrustedProxyIPs {\n        if remoteIP.String() == trustedIP {\n            return true\n        }\n    }\n\n    return false\n}\n```\n\nAdd configuration option:\n\n```ini\n[auth]\nENABLE_REVERSE_PROXY_AUTHENTICATION = false\nREVERSE_PROXY_AUTHENTICATION_HEADER = X-WEBAUTH-USER\n; Comma-separated list of trusted proxy IPs (default: 127.0.0.1)\nTRUSTED_PROXY_IPS = 127.0.0.1,::1\n; Whether to require trusted proxy validation (recommended: true)\nREQUIRE_TRUSTED_PROXY = true\n```\n\n## References\n\n- [CWE-290: Authentication Bypass by Spoofing](https://cwe.mitre.org/data/definitions/290.html)\n- [OWASP: Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)\n- [OWASP Top 10 2021 - A07: Identification and Authentication Failures](https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/)",
      "id": "GHSA-w6j9-vw59-27wv",
      "modified": "2026-06-22T17:09:51Z",
      "published": "2026-06-22T17:09:51Z",
      "references": [
        {
          "type": "WEB",
          "url": "https://github.com/gogs/gogs/security/advisories/GHSA-w6j9-vw59-27wv"
        },
        {
          "type": "WEB",
          "url": "https://github.com/gogs/gogs/pull/8264"
        },
        {
          "type": "WEB",
          "url": "https://github.com/gogs/gogs/commit/0089c4c8e5b8d99eb6e5c8727f8f40d765f1f58a"
        },
        {
          "type": "PACKAGE",
          "url": "https://github.com/gogs/gogs"
        },
        {
          "type": "WEB",
          "url": "https://github.com/gogs/gogs/releases/tag/v0.14.3"
        }
      ],
      "schema_version": "1.4.0",
      "severity": [
        {
          "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P",
          "type": "CVSS_V4"
        }
      ],
      "summary": "Gogs has an Authentication Bypass via Unvalidated Reverse Proxy Headers"
    }