GHSA-x732-6j76-qmhm CVE-2025-71399
Better Auth's rou3 Dependency has Double-Slash Path Normalization which can Bypass disabledPaths Config and Rate Limits
- Severity
- 8.8 / 10
- High · CVSS 4.0
- Exploit chance (EPSS)
- 0.52%
- Chance of exploitation in the next 30 days. Higher than 44.18% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Fix
1.4.5- Upgrade better-auth to this version or later
Description
Summary
An issue in the underlying router library rou3 can cause /path and //path to be treated as identical routes. If your environment does not normalize incoming URLs (e.g., by collapsing multiple slashes), this can allow bypasses of disabledPaths and path-based rate limits.
Details
Better Auth uses better-call, which internally relies on rou3 for routing. Affected versions of rou3 normalize paths by removing empty segments. As a result:
/sign-in/email//sign-in/email///sign-in/email
…all resolve to the same route.
Some production setups automatically collapse multiple slashes. This includes:
- Vercel with Nextjs (default)
- Cloudflare - when normalize to urls origin is enabled (https://developers.cloudflare.com/rules/normalization/settings/#normalize-urls-to-origin)
In these environments and other configurations where //path reach Better Auth as /path, the issue does not apply.
Fix
Updating rou3 to the latest version resolves the issue:
- better-call previously depended on
"rou3": "^0.5.1" - The fix was introduced after that version (commit: https://github.com/h3js/rou3/commit/f60b43fa648399534507c9ac7db36d705b8874c3)
Better Auth recommends:
- Upgrading to Better Auth v1.4.5 or later, which includes the updated rou3.
- Ensuring the proxy normalizes URLs.
- If project maintainers cannot upgrade yet, they can protect their app by normalizing url before it reaches better-auth handler. See example below:
const req = new Request(...) // this would be the actual request object
const url = new URL(req.url);
const normalizedPath = url.pathname.replace(/\/+/g, "/");
if (url.pathname !== normalizedPath) {
url.pathname = normalizedPath;
// Update the raw request pathname
Object.defineProperty(req, "url", {
value: url.toString(),
writable: true,
configurable: true,
});
}
Impact
- Bypass
disabledPaths - Bypass path-based rate limits
The impact of bypassing disabled paths could vary based on a project's configuration.
Affected versions
npm
| Package | Vulnerable | Fixed in |
|---|---|---|
| better-auth | < 1.4.5 |
1.4.5 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
better-auth npm → 1.4.5
- npm
npm install better-auth@1.4.5- yarn
yarn add better-auth@1.4.5- pnpm
pnpm add better-auth@1.4.5
Severity breakdown
CVSS 4.0 8.8
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:H/SC:N/SI:N/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
- Attack vector
- Network
- Attack complexity
- Low
- Attack requirements
- None
- Privileges required
- None
- User interaction
- None
- Confidentiality (vulnerable system)
- Low
- Integrity (vulnerable system)
- Low
- Availability (vulnerable system)
- High
- Confidentiality (subsequent systems)
- None
- Integrity (subsequent systems)
- None
- Availability (subsequent systems)
- None
- Exploit maturity
- Not defined
- Scope
- X
CVSS 3.1 8.6
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- Low
- Integrity
- Low
- Availability
- High
Weakness
CWE-400: Uncontrolled Resource Consumption
The product does not properly control the allocation and maintenance of a limited resource.
How to prevent it
- Architecture and Design: Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
- Architecture and Design: Mitigation of resource exhaustion attacks requires that the target system either: recognizes the attack and denies that user further access for a given amount of time, or uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed. The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question. The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
- Architecture and Design: Ensure that protocols have specific limits of scale placed on them.
- Implementation: Ensure that all failures in resource allocation place the system into a safe posture.
CWE-41: Improper Resolution of Path Equivalence
The product is vulnerable to file system contents disclosure through path equivalence. Path equivalence involves the use of special characters in file and directory names. The associated manipulations are intended to generate multiple names for the same object.
How to prevent it
- Implementation: Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
- Implementation: Use and specify an output encoding that can be handled by the downstream component that is reading the output. Common encodings include ISO-8859-1, UTF-7, and UTF-8. When an encoding is not specified, a downstream component may choose a different encoding, either by assuming a default encoding or automatically inferring which encoding is being used, which can be erroneous. When the encodings are inconsistent, the downstream component might treat some character or byte sequences as special, even if they are not special in the original encoding. Attackers might then be able to exploit this discrepancy and conduct injection attacks; they even might be able to bypass protection mechanisms that assume the original encoding is also being used by the downstream component.
- Implementation: Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180). Make sure that the application does not decode the same input twice (CWE-174). Such errors could be used to bypass allowlist validation schemes by introducing dangerous inputs after they have been checked.
References
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-r4xp-prcw-77qf better-auth: OAuth Proxy lets an attacker sign in as another user | Critical | Also affects better-auth |
| GHSA-965c-763c-88jm better-auth: OAuth state can be used as a Magic Link to sign in as another user | Critical | Also affects better-auth |
| GHSA-44jh-23m7-hpcf @better-auth/drizzle-adapter: Concurrent requests can exceed rate limits on PostgreSQL | Medium | Also affects better-auth |
| GHSA-q84f-53jg-9ppm better-auth: Device login approval does not show the requesting client or permissions | High | Also affects better-auth |
| GHSA-qq9h-g4jm-xgf3 Better Auth: Account takeover via pre-account hijacking on magic-link and email-OTP sign-in | High | Also affects better-auth |
| GHSA-2vg6-77g8-24mp Better Auth: Stale sessions persist after user deletion across admin, anonymous, and SCIM flows | Medium | Also affects better-auth |
| GHSA-7w99-5wm4-3g79 @better-auth/oauth-provider's OAuth authorization-code grant allows concurrent redemption when two token requests race the find-then-delete primitive | High | Also affects better-auth |
| GHSA-392p-2q2v-4372 Better Auth: OAuth refresh-token rotation forks the token family on concurrent redemption | High | Also affects better-auth |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor