GHSA-vp58-j275-797x

Suggest an improvement
Source
https://github.com/advisories/GHSA-vp58-j275-797x
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/02/GHSA-vp58-j275-797x/GHSA-vp58-j275-797x.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-vp58-j275-797x
Published
2025-02-24T20:49:50Z
Modified
2025-03-03T13:44:59Z
Severity
  • 9.3 (Critical) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N CVSS Calculator
Summary
Better Auth allows bypassing the trustedOrigins Protection which leads to ATO
Details

Summary

A bypass was found for wildcard or absolute URLs trustedOrigins configurations and opens the victims website to a Open Redirect vulnerability, where it can be used to steal the reset password token of a victims account by changing the "callbackURL" parameter value to a website owned by the attacker.

Details

Absolute URLs

The issue here appears in the middleware, specifically. This protection is not sufficiente and it allows attackers to exploit a open redirect vulnerability, by using the payload /\/example.com. We can check this is a valid URL ( or it will be a valid URL because the URL parser fix it for us ), by checking the image bellow:

image

// trustedOrigins = [ "https://example.com" ]
validateURL("https://attacker.com", "callbackURL") // ❌ APIError, No Redirect
validateURL("/\/attacker.com", "callbackURL")       // ✅ Redirect to http://attacker.com

Regex

The issue here is because the regex is not strong enough [^/\\]*?\.example\.com[/\\]*? ( this is the regex it will be created if we have a wildcard as the trustedOrigins config ), but we can bypass by using a payload like:

// trustedOrigins = [ "*.example.com" ]
  ┌──────────────────┐       ┌────────────────┐       ┌─────────────────┐
  │ None of [ "/\" ] │ ────▶ │ ".example.com" │ ────▶ │ One of [ "/\" ] │
  └──────────────────┘       └────────────────┘       └─────────────────┘
          demo                  .example.com                    /               ✅ Redirect to https://example.com
          demo                  .attacker.com                   /               ❌ APIError, no redirect
   http:attacker.com?           .example.com                    /               ✅ Redirect to http://attacker.com

This works because : and ? are special chars in a URL, so when the URL parser sees, http: it will fix our happily fix our URL to http://attacker.com? and make .example.com as parameter, thus, bypassing this check.

PoC

We can PoC the open redirect by using the demo.better-auth.com. If we access the URL bellow, we are redirected to example.com: - https://demo.better-auth.com/api/auth/reset-password/x?callbackURL=/\/example.com

Impact

Every single website using the better-auth library, is vulnerable to un-auth open redirect and more importantilly, vulnerable to potential one click account take over vulnerability, as the attacker can send the victim a email to reset their account while changing the "redirectTo" parameter here, and when the victim clicks on the link, the reset token is sent to the attackers website, which then a attacker could use that token to reset the password of the victims account.

Database specific
{
    "github_reviewed_at": "2025-02-24T20:49:50Z",
    "cwe_ids": [
        "CWE-601"
    ],
    "nvd_published_at": null,
    "severity": "CRITICAL",
    "github_reviewed": true
}
References

Affected packages

npm / better-auth

Package

Affected ranges

Type
SEMVER
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
1.1.21

Database specific

{
    "last_known_affected_version_range": "<= 1.1.20"
}