Every CVE Search/ Get API key

CVE-2026-79662

Ech0 before 4.7.3 OAuth Redirect URI Validation Bypass

8.8 HighFix available

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
Passive

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
None

Exploit likelihood

0.32%Up 0.1 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.8

Ech0 before 4.7.3 OAuth Redirect URI Validation Bypass

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Record
CVE-2026-79662
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
CVSS 3.1
8.0 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N
Weakness
CWE-601
Updated
2026-11-02
EUVDEUVD-2026-65452 8.8

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Record
EUVD-2026-65452
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-m5w8-4879-f4pc 8.8

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in...

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Record
GHSA-m5w8-4879-f4pc
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
8.0 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N
Weakness
CWE-601
Updated
2026-11-02
GitHub AdvisoriesGHSA-p64j-f4x9-wq66 8.0

Ech0's OAuth redirect URI validation ignores path component, enables exchange-code theft

Summary

parseAndValidateClientRedirect at internal/service/auth/auth.go:448 validates OAuth client-redirect URIs by comparing only scheme and host against the admin-configured allowlist. Path, query, and fragment are ignored. The initiator at /oauth/:provider/login embeds the caller-supplied redirect_uri verbatim into the signed state JWT without any validation at login time. Alice submits a crafted redirect_uri whose host matches an allowed origin but whose path points to any page on that host. After the provider exchange, Ech0 redirects the victim to the attacker-chosen path with the one-time exchange code in the query string. If the chosen path leaks the URL via Referer, analytics, or an open redirect, the attacker trades the code at POST /api/auth/exchange for the victim's access and refresh tokens. RFC 6749 §3.1.2 requires exact redirect URI matching.

Details

Validation at internal/service/auth/auth.go:448:

matched := false
for _, item := range allowed {
    allowURL, parseErr := url.Parse(strings.TrimSpace(item))
    if parseErr != nil || allowURL == nil || allowURL.Host == "" {
        continue
    }
    if strings.EqualFold(redirectURL.Scheme, allowURL.Scheme) &&
       strings.EqualFold(redirectURL.Host, allowURL.Host) {
        matched = true
        break
    }
}

Scheme and host compared via EqualFold. Path, query, fragment all ignored. An allowlist entry of https://myecho.example.com/dashboard matches every https://myecho.example.com/<anything> the attacker sends.

Login flow at internal/service/auth/auth.go:141 (GetOAuthLoginURL) and the handler at internal/handler/auth/oauth.go:43:

redirectURI := ctx.Query("redirect_uri")
redirectURL, err := h.authService.GetOAuthLoginURL(provider, redirectURI)
// ...
ctx.Redirect(302, redirectURL)

No validation at login. The raw redirect_uri query parameter is passed to GetOAuthLoginURL, which encodes it into the signed state JWT alongside the provider name and nonce. The state JWT travels through the OAuth provider and returns on the callback.

At callback time, parseAndValidateClientRedirect(oauthState.Redirect) fires at internal/service/auth/auth.go:372 and :427 inside the callback handler chain. Scheme and host are the only gates on the attacker-chosen URI.

After validation, the server generates a one-time exchange code and redirects the browser to the attacker-chosen path:

302 Location: https://myecho.example.com/<attacker-path>?code=<one-time-exchange-code>

The code is valid at the public endpoint POST /api/auth/exchange for up to 60 seconds (single-use). An attacker who reads the code from the URL trades it for the victim's access token and refresh token.

Proof of Concept

Default install with OAuth2 configured. Admin allows https://myecho.example.com/dashboard as the return URL; Alice sends a crafted login link whose redirect points elsewhere on the same host:

import requests, urllib.parse, base64, json
TARGET = "http://localhost:8300"

# Admin setup: enable OAuth with one allowed return URL (dashboard).
owner = requests.post(f"{TARGET}/api/login",
                      json={"username": "owner", "password": "owner-pw"}
                     ).json()["data"]["access_token"]
requests.put(f"{TARGET}/api/oauth2/settings",
             headers={"Authorization": f"Bearer {owner}",
                      "content-type": "application/json"},
             json={"enable": True, "provider": "github",
                   "client_id": "poc-client-id", "client_secret": "poc-client-secret",
                   "redirect_uri": f"{TARGET}/oauth/github/callback",
                   "scopes": ["read:user"],
                   "auth_url": "https://github.com/login/oauth/authorize",
                   "token_url": "https://github.com/login/oauth/access_token",
                   "user_info_url": "https://api.github.com/user",
                   "auth_redirect_allowed_return_urls":…
Record
GHSA-p64j-f4x9-wq66
CVSS 3.1
8.0 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N
Weakness
CWE-601, CWE-1173
Updated
2026-11-02
NVD 8.8

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Record
CVE-2026-79662
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
8.0 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N
Weakness
CWE-601
Updated
2026-11-02
OSV 8.8

Ech0 before 4.7.3 OAuth Redirect URI Validation Bypass

Ech0 through 4.5.6 contains an OAuth redirect URI validation vulnerability in parseAndValidateClientRedirect (internal/service/auth/auth.go) that compares only the scheme and host of the client-supplied redirect_uri against the admin-configured allowlist, ignoring path, query, and fragment components. The redirect_uri is embedded into the signed state JWT at login time without validation. An attacker can craft a redirect_uri whose host matches an allowed origin but whose path is attacker-influenced; after the OAuth exchange the victim is redirected to that path with a one-time exchange code in the query string. If the code leaks (e.g., via Referer, analytics, or an open redirect on that host), the attacker can trade it at the public POST /api/auth/exchange endpoint for the victim's access and refresh tokens. Fixed in 4.7.3.

Record
CVE-2026-79662
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
Weakness
CWE-601
Updated
2026-11-02
OSVGHSA-p64j-f4x9-wq66 8.0

Ech0's OAuth redirect URI validation ignores path component, enables exchange-code theft

Summary

parseAndValidateClientRedirect at internal/service/auth/auth.go:448 validates OAuth client-redirect URIs by comparing only scheme and host against the admin-configured allowlist. Path, query, and fragment are ignored. The initiator at /oauth/:provider/login embeds the caller-supplied redirect_uri verbatim into the signed state JWT without any validation at login time. Alice submits a crafted redirect_uri whose host matches an allowed origin but whose path points to any page on that host. After the provider exchange, Ech0 redirects the victim to the attacker-chosen path with the one-time exchange code in the query string. If the chosen path leaks the URL via Referer, analytics, or an open redirect, the attacker trades the code at POST /api/auth/exchange for the victim's access and refresh tokens. RFC 6749 §3.1.2 requires exact redirect URI matching.

Details

Validation at internal/service/auth/auth.go:448:

matched := false
for _, item := range allowed {
    allowURL, parseErr := url.Parse(strings.TrimSpace(item))
    if parseErr != nil || allowURL == nil || allowURL.Host == "" {
        continue
    }
    if strings.EqualFold(redirectURL.Scheme, allowURL.Scheme) &&
       strings.EqualFold(redirectURL.Host, allowURL.Host) {
        matched = true
        break
    }
}

Scheme and host compared via EqualFold. Path, query, fragment all ignored. An allowlist entry of https://myecho.example.com/dashboard matches every https://myecho.example.com/<anything> the attacker sends.

Login flow at internal/service/auth/auth.go:141 (GetOAuthLoginURL) and the handler at internal/handler/auth/oauth.go:43:

redirectURI := ctx.Query("redirect_uri")
redirectURL, err := h.authService.GetOAuthLoginURL(provider, redirectURI)
// ...
ctx.Redirect(302, redirectURL)

No validation at login. The raw redirect_uri query parameter is passed to GetOAuthLoginURL, which encodes it into the signed state JWT alongside the provider name and nonce. The state JWT travels through the OAuth provider and returns on the callback.

At callback time, parseAndValidateClientRedirect(oauthState.Redirect) fires at internal/service/auth/auth.go:372 and :427 inside the callback handler chain. Scheme and host are the only gates on the attacker-chosen URI.

After validation, the server generates a one-time exchange code and redirects the browser to the attacker-chosen path:

302 Location: https://myecho.example.com/<attacker-path>?code=<one-time-exchange-code>

The code is valid at the public endpoint POST /api/auth/exchange for up to 60 seconds (single-use). An attacker who reads the code from the URL trades it for the victim's access token and refresh token.

Proof of Concept

Default install with OAuth2 configured. Admin allows https://myecho.example.com/dashboard as the return URL; Alice sends a crafted login link whose redirect points elsewhere on the same host:

import requests, urllib.parse, base64, json
TARGET = "http://localhost:8300"

# Admin setup: enable OAuth with one allowed return URL (dashboard).
owner = requests.post(f"{TARGET}/api/login",
                      json={"username": "owner", "password": "owner-pw"}
                     ).json()["data"]["access_token"]
requests.put(f"{TARGET}/api/oauth2/settings",
             headers={"Authorization": f"Bearer {owner}",
                      "content-type": "application/json"},
             json={"enable": True, "provider": "github",
                   "client_id": "poc-client-id", "client_secret": "poc-client-secret",
                   "redirect_uri": f"{TARGET}/oauth/github/callback",
                   "scopes": ["read:user"],
                   "auth_url": "https://github.com/login/oauth/authorize",
                   "token_url": "https://github.com/login/oauth/access_token",
                   "user_info_url": "https://api.github.com/user",
                   "auth_redirect_allowed_return_urls":…
Record
GHSA-p64j-f4x9-wq66
CVSS 3.1
8.0 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N
Weakness
CWE-1173, CWE-601
Updated
2026-11-02
OSVGO-2026-5531 No score

Ech0's OAuth redirect URI validation ignores path component, enables exchange-code theft in github.com/lin-snow/ech0

Ech0's OAuth redirect URI validation ignores path component, enables exchange-code theft in github.com/lin-snow/ech0

Record
GO-2026-5531
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/lin-snow/Ech0
Go
before 1.4.8-0.20260503040728-a7e8b8e84bd1
1.4.8-0.20260503040728-a7e8b8e84bd1
github.com/lin-snow/ech0
Go
before 1.4.8-0.20260503040728-a7e8b8e84bd1
1.4.8-0.20260503040728-a7e8b8e84bd1

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-79662 is a high vulnerability (CVSS 8.8) in Lin-snow Ech0, published May 7, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.32%, the 25th percentile. Fixed in github.com/lin-snow/Ech0 1.4.8-0.20260503040728-a7e8b8e84bd1.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open