CVE-2026-53523: Nezha Monitoring: OAuth2 Redirect URL — Host Header Injection
1. Description
The getRedirectURL function in oauth2.go:22-29 constructs the OAuth2 callback URL by concatenating the request’s Host header with a fixed path, with zero validation of the Host header:
func getRedirectURL(c *gin.Context) string {
scheme := "http://"
referer := c.Request.Referer()
if forwardedProto := c.Request.Header.Get("X-Forwarded-Proto"); forwardedProto == "https" || strings.HasPrefix(referer, "https://") {
scheme = "https://"
}
return scheme + c.Request.Host + "/api/v1/oauth2/callback"
}
File: cmd/dashboard/controller/oauth2.go:22-29
This function is called from oauth2redirect() at line 53:
func oauth2redirect(c *gin.Context) (*model.Oauth2LoginResponse, error) {
// ...
redirectURL := getRedirectURL(c)
o2conf := o2confRaw.Setup(redirectURL)
// ...
url := o2conf.AuthCodeURL(state, oauth2.AccessTypeOnline)
return &model.Oauth2LoginResponse{Redirect: url}, nil
}
The redirectURL is passed into o2confRaw.Setup(redirectURL) which configures the OAuth2 Config.RedirectURL field (oauth2config.go:22-33). This RedirectURL is sent to the OAuth2 provider (e.g., GitHub, Google, Microsoft) as the callback endpoint. The OAuth2 provider will redirect the user’s browser — along with the authorization code — to this URL after the user authenticates.
The security issue is that c.Request.Host is directly user-controllable via the HTTP Host header. An attacker who can control which Host header reaches the oauth2redirect handler can:
- Set
Host: evil.com getRedirectURLreturnshttps://evil.com/api/v1/oauth2/callback- The OAuth2 provider redirects the victim’s auth code to
evil.com - The attacker’s server at
evil.comcaptures the auth code - The attacker exchanges the code for an access token, binding the victim’s OAuth identity to the attacker’s dashboard account
The scheme detection (lines 24-27) uses X-Forwarded-Proto and the Referer header, both of which are also user-controllable in certain configurations, so the attacker can force https:// scheme in the redirect URL.
The oauth2callback handler at line 129 later uses state.RedirectURL (which is stored in singleton.Cache at line 65) when calling exchangeOpenId at line 152. The cached redirectURL was set during the initial oauth2redirect call, tying the attack flow together.
2. PoC
A conceptual attack (no Docker needed):
Scenario: OAuth2 provider has loose redirect URI validation
(e.g., allows wildcard subdomain matching)
1. Attacker crafts a URL to the dashboard's OAuth2 login endpoint
with a modified Host header:
GET /api/v1/oauth2/github HTTP/1.1
Host: attacker-controlled.com
X-Forwarded-Proto: https
References
Code Behaviors & Features
Detect and mitigate CVE-2026-53523 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →