Common Weakness Enumeration

CWE-613

Allowed-with-Review

Insufficient Session Expiration

Abstraction: Base · Status: Incomplete

According to WASC, "Insufficient Session Expiration is when a web site permits an attacker to reuse old session credentials or session IDs for authorization."

1087 vulnerabilities reference this CWE, most recent first.

GHSA-34M5-CM5W-XF6V

Vulnerability from github – Published: 2026-10-19 18:32 – Updated: 2026-10-19 18:32
VLAI
Details

Tokens associated with user sessions are not revoked when the corresponding user session is terminated, unless another SSO request is initiated. This occurs when the session-bound token feature is enabled with token binding validation and the "Revoke token upon user logout" option is not active. The software fails to automatically invalidate session-bound tokens upon user session termination.

This vulnerability exists when token binding validation is enabled. As a result, a malicious actor possessing a valid session-bound token could exploit this condition to maintain unauthorized access to applications and resources even after the associated user session has ended, potentially leading to the exposure of sensitive user data.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-13173"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-10-19T17:16:59Z",
    "severity": "MODERATE"
  },
  "details": "Tokens associated with user sessions are not revoked when the corresponding user session is terminated, unless another SSO request is initiated. This occurs when the session-bound token feature is enabled with token binding validation and the \"Revoke token upon user logout\" option is not active. The software fails to automatically invalidate session-bound tokens upon user session termination.\n\nThis vulnerability exists when token binding validation is enabled. As a result, a malicious actor possessing a valid session-bound token could exploit this condition to maintain unauthorized access to applications and resources even after the associated user session has ended, potentially leading to the exposure of sensitive user data.",
  "id": "GHSA-34m5-cm5w-xf6v",
  "modified": "2026-10-19T18:32:13Z",
  "published": "2026-10-19T18:32:13Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-13173"
    },
    {
      "type": "WEB",
      "url": "https://security.docs.wso2.com/en/latest/security-announcements/security-advisories/2026/WSO2-2025-4727"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-355W-RX9G-PWW7

Vulnerability from github – Published: 2026-10-17 21:31 – Updated: 2026-10-17 21:31
VLAI
Details

Vikunja 2.3.0 before 2.7.0 contains an improper session validation vulnerability that allows attackers to keep WebSocket access after revocation because handleAuth never checks the JWT sid claim against the sessions table. Attackers holding a stolen access token can open or maintain connections to /api/v2/ws after session deletion or TOTP enrollment, continuing to receive the victim's notification.created pushes, including comment, task and project content.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-111917"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-10-17T19:16:34Z",
    "severity": "HIGH"
  },
  "details": "Vikunja 2.3.0 before 2.7.0 contains an improper session validation vulnerability that allows attackers to keep WebSocket access after revocation because handleAuth never checks the JWT sid claim against the sessions table. Attackers holding a stolen access token can open or maintain connections to /api/v2/ws after session deletion or TOTP enrollment, continuing to receive the victim\u0027s notification.created pushes, including comment, task and project content.",
  "id": "GHSA-355w-rx9g-pww7",
  "modified": "2026-10-17T21:31:19Z",
  "published": "2026-10-17T21:31:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-4hv6-xc92-j86g"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-111917"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/vikunja-2.3.0-before-2.7.0-websocket-authentication-ignores-session-revocation"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-35C6-2WX7-593F

Vulnerability from github – Published: 2026-03-06 18:31 – Updated: 2026-05-06 15:32
VLAI
Details

The WebSocket backend uses charging station identifiers to uniquely associate sessions but allows multiple endpoints to connect using the same session identifier. This implementation results in predictable session identifiers and enables session hijacking or shadowing, where the most recent connection displaces the legitimate charging station and receives backend commands intended for that station. This vulnerability may allow unauthorized users to authenticate as other users or enable a malicious actor to cause a denial-of-service condition by overwhelming the backend with valid session requests.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-20748"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-03-06T16:16:09Z",
    "severity": "MODERATE"
  },
  "details": "The WebSocket backend uses charging station identifiers to uniquely associate sessions but allows multiple endpoints to connect using the same session identifier. This implementation results in predictable session identifiers and enables session hijacking or shadowing, where the most recent connection displaces the legitimate charging station and receives backend commands intended for that station. This vulnerability may allow unauthorized users to authenticate as other users or enable\u00a0a malicious actor to cause a denial-of-service condition by overwhelming the backend with valid session requests.",
  "id": "GHSA-35c6-2wx7-593f",
  "modified": "2026-05-06T15:32:32Z",
  "published": "2026-03-06T18:31:13Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-20748"
    },
    {
      "type": "WEB",
      "url": "https://github.com/cisagov/CSAF/blob/develop/csaf_files/OT/white/2026/icsa-26-062-08.json"
    },
    {
      "type": "WEB",
      "url": "https://www.cisa.gov/news-events/ics-advisories/icsa-26-062-08"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-365R-WJFH-HWPV

Vulnerability from github – Published: 2026-03-21 00:31 – Updated: 2026-05-06 18:30
VLAI
Details

The WebSocket backend uses charging station identifiers to uniquely associate sessions but allows multiple endpoints to connect using the same session identifier. This implementation results in predictable session identifiers and enables session hijacking or shadowing, where the most recent connection displaces the legitimate charging station and receives backend commands intended for that station. This vulnerability may allow unauthorized users to authenticate as other users or enable a malicious actor to cause a denial-of-service condition by overwhelming the backend with valid session requests.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-32663"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-03-20T23:16:44Z",
    "severity": "MODERATE"
  },
  "details": "The WebSocket backend uses charging station identifiers to uniquely associate sessions but allows multiple endpoints to connect using the same session identifier. This implementation results in predictable session identifiers and enables session hijacking or shadowing, where the most recent connection displaces the legitimate charging station and receives backend commands intended for that station. This vulnerability may allow unauthorized users to authenticate as other users or enable\u00a0a malicious actor to cause a denial-of-service condition by overwhelming the backend with valid session requests.",
  "id": "GHSA-365r-wjfh-hwpv",
  "modified": "2026-05-06T18:30:24Z",
  "published": "2026-03-21T00:31:43Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32663"
    },
    {
      "type": "WEB",
      "url": "https://github.com/cisagov/CSAF/blob/develop/csaf_files/OT/white/2026/icsa-26-078-08.json"
    },
    {
      "type": "WEB",
      "url": "https://www.cisa.gov/news-events/ics-advisories/icsa-26-078-08"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-377J-WJ38-4728

Vulnerability from github – Published: 2025-09-04 14:06 – Updated: 2025-09-05 16:10
VLAI
Summary
Weblate has a long session expiry when verifying second factor
Details

Impact

The verification of the second factor had too long a session expiry. The long session expiry could be used to circumvent rate limiting of the second factor.

Patches

This issue has been addressed in Weblate 5.13.1 via https://github.com/WeblateOrg/weblate/pull/16002.

References

Thanks to Nahid Hasan Limon for reporting this issue responsibly.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "Weblate"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.13.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-58352"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-09-04T14:06:15Z",
    "nvd_published_at": "2025-09-05T00:15:32Z",
    "severity": "LOW"
  },
  "details": "### Impact\nThe verification of the second factor had too long a session expiry. The long session expiry could be used to circumvent rate limiting of the second factor.\n\n\n### Patches\nThis issue has been addressed in Weblate 5.13.1 via https://github.com/WeblateOrg/weblate/pull/16002.\n\n### References\nThanks to Nahid Hasan Limon for reporting this issue responsibly.",
  "id": "GHSA-377j-wj38-4728",
  "modified": "2025-09-05T16:10:49Z",
  "published": "2025-09-04T14:06:15Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/WeblateOrg/weblate/security/advisories/GHSA-377j-wj38-4728"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-58352"
    },
    {
      "type": "WEB",
      "url": "https://github.com/WeblateOrg/weblate/pull/16002"
    },
    {
      "type": "WEB",
      "url": "https://github.com/WeblateOrg/weblate/commit/0b46fe596231dd456283ead66699ae5516f23908"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/WeblateOrg/weblate"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Weblate has a long session expiry when verifying second factor"
}

GHSA-3785-76F5-G4RM

Vulnerability from github – Published: 2024-10-16 09:30 – Updated: 2024-10-16 09:30
VLAI
Details

The logout operation in the CloudStack web interface does not expire the user session completely which is valid until expiry by time or restart of the backend service. An attacker that has access to a user's browser can use an unexpired session to gain access to resources owned by the logged out user account. This issue affects Apache CloudStack from 4.15.1.0 through 4.18.2.3; and from 4.19.0.0 through 4.19.1.1.

Users are recommended to upgrade to Apache CloudStack 4.18.2.4 or 4.19.1.2, or later, which addresses this issue.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-45462"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-10-16T08:15:05Z",
    "severity": "MODERATE"
  },
  "details": "The logout operation in the CloudStack web interface does not expire the user session completely which is valid until expiry by time or restart of the backend service. An attacker that has access to a user\u0027s browser can use an unexpired session to gain access to resources owned by the logged out user account. This issue affects Apache CloudStack from 4.15.1.0 through 4.18.2.3; and from 4.19.0.0 through 4.19.1.1.\n\n\n\n\nUsers are recommended to upgrade to Apache CloudStack 4.18.2.4 or 4.19.1.2, or later, which addresses this issue.",
  "id": "GHSA-3785-76f5-g4rm",
  "modified": "2024-10-16T09:30:31Z",
  "published": "2024-10-16T09:30:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-45462"
    },
    {
      "type": "WEB",
      "url": "https://cloudstack.apache.org/blog/security-release-advisory-4.18.2.4-4.19.1.2"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread/ktsfjcnj22x4kg49ctock3d9tq7jnvlo"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-38GC-W4H9-7PMF

Vulnerability from github – Published: 2021-12-30 00:00 – Updated: 2022-01-08 00:00
VLAI
Details

An insufficient session expiration vulnerability in the CGI program of the Zyxel NBG6604 firmware could allow a remote attacker to access the device if the correct token can be intercepted.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-35034"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-12-29T13:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "An insufficient session expiration vulnerability in the CGI program of the Zyxel NBG6604 firmware could allow a remote attacker to access the device if the correct token can be intercepted.",
  "id": "GHSA-38gc-w4h9-7pmf",
  "modified": "2022-01-08T00:00:41Z",
  "published": "2021-12-30T00:00:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-35034"
    },
    {
      "type": "WEB",
      "url": "https://www.zyxel.com/support/Zyxel_security_advisory_for_sensitive_information_vulnerabilities_of_NBG6604_home_router.shtml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-38J9-7PP9-2HJW

Vulnerability from github – Published: 2021-06-08 18:52 – Updated: 2021-06-17 20:00
VLAI
Summary
Invalid session token expiration
Details

HashiCorp Vault and Vault Enterprise allowed the renewal of nearly-expired token leases and dynamic secret leases (specifically, those within 1 second of their maximum TTL), which caused them to be incorrectly treated as non-expiring during subsequent use. Fixed in 1.5.9, 1.6.5, and 1.7.2.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/hashicorp/vault"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.7.0"
            },
            {
              "fixed": "1.7.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/hashicorp/vault"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.6.0"
            },
            {
              "fixed": "1.6.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/hashicorp/vault"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.10.0"
            },
            {
              "fixed": "1.5.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2021-32923"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-06-04T18:42:40Z",
    "nvd_published_at": "2021-06-03T11:15:00Z",
    "severity": "HIGH"
  },
  "details": "HashiCorp Vault and Vault Enterprise allowed the renewal of nearly-expired token leases and dynamic secret leases (specifically, those within 1 second of their maximum TTL), which caused them to be incorrectly treated as non-expiring during subsequent use. Fixed in 1.5.9, 1.6.5, and 1.7.2.",
  "id": "GHSA-38j9-7pp9-2hjw",
  "modified": "2021-06-17T20:00:42Z",
  "published": "2021-06-08T18:52:05Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32923"
    },
    {
      "type": "WEB",
      "url": "https://discuss.hashicorp.com/t/hcsec-2021-15-vault-renewed-nearly-expired-leases-with-incorrect-non-expiring-ttls/24603"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202207-01"
    },
    {
      "type": "WEB",
      "url": "https://www.hashicorp.com/blog/category/vault"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Invalid session token expiration "
}

GHSA-38XM-RJ5R-36VX

Vulnerability from github – Published: 2024-01-26 21:30 – Updated: 2024-04-01 09:30
VLAI
Details

A vulnerability was found in Totolink T8 4.1.5cu.833_20220905. It has been rated as problematic. Affected by this issue is some unknown functionality of the file /cgi-bin/cstecgi.cgi. The manipulation leads to session expiration. The attack may be launched remotely. The complexity of an attack is rather high. The exploitation is known to be difficult. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-252188. NOTE: The vendor was contacted early about this disclosure but did not respond in any way.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-0944"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-01-26T20:15:54Z",
    "severity": "LOW"
  },
  "details": "A vulnerability was found in Totolink T8 4.1.5cu.833_20220905. It has been rated as problematic. Affected by this issue is some unknown functionality of the file /cgi-bin/cstecgi.cgi. The manipulation leads to session expiration. The attack may be launched remotely. The complexity of an attack is rather high. The exploitation is known to be difficult. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-252188. NOTE: The vendor was contacted early about this disclosure but did not respond in any way.",
  "id": "GHSA-38xm-rj5r-36vx",
  "modified": "2024-04-01T09:30:31Z",
  "published": "2024-01-26T21:30:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-0944"
    },
    {
      "type": "WEB",
      "url": "https://drive.google.com/file/d/1YPisSnxM5CwSLKFgs9w5k5MtNUgiijVo/view?usp=sharing"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?ctiid.252188"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?id.252188"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?submit.269681"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-392P-2Q2V-4372

Vulnerability from github – Published: 2026-07-07 20:55 – Updated: 2026-07-20 19:24
VLAI
Summary
Better Auth: OAuth refresh-token rotation forks the token family on concurrent redemption
Details

Am I affected?

Users are affected if all of the following are true:

  • Their project depends on @better-auth/oauth-provider at a version >= 1.6.0, < 1.6.11, or uses the embedded plugin in better-auth >= 1.4.8-beta.7, < 1.6.0.
  • At least one OAuth client served by their application's authorization server requests the offline_access scope, so refresh tokens are minted.
  • Concurrent redemption of the same refresh token is reachable: an SPA shares one refresh token across browser tabs without a mutex, a mobile client retries after a transient failure, an attacker who has stolen a refresh token times two requests, or a service worker queues offline requests.

If developer applications do not request offline_access for any client, no refresh tokens are minted and they are not exposed.

Fix:

  1. Upgrade to @better-auth/oauth-provider@1.6.11 or later.
  2. If developers cannot upgrade, see workarounds below.

Summary

The OAuth provider's POST /oauth2/token endpoint, on the refresh_token grant, performs a non-atomic read / validate / revoke / mint sequence on the oauthRefreshToken row. Two concurrent requests presenting the same parent refresh token both pass the revocation check before either revoke completes, so each mints a fresh refresh token. The replay-detection branch only fires when revoked is already truthy at read time, which is exactly the state concurrent attackers race past. The result is a forked refresh-token family from a single parent token.

Details

The adapter.update predicate on the parent row is keyed on id only; it does not include revoked IS NULL, so two concurrent updates both succeed (last-write-wins, no error path). The schema does not declare unique on oauthRefreshToken.token, so concurrent creates do not collide on a unique-key violation either.

RFC 9700 §4.14 (OAuth Security Best Current Practice) prescribes refresh-token family invalidation on detected reuse; this implementation tries to enforce that contract through the revoked check, but the check is not atomic with the consumption step. Token rotation issues a new refresh token with each call, so a single stolen refresh token grants indefinite access until the row is revoked or its refreshTokenExpiresAt (default 7 days) passes. Rotation refreshes that window each call.

The fix lands an atomic compare-and-swap on the parent row inside the rotation primitive (UPDATE ... WHERE id = ? AND revoked IS NULL with a rowcount check), so the losing rotation fails closed with invalid_grant and the parent row stays marked revoked. Subsequent replay of the original refresh token then trips the existing family-invalidation guard. The schema gains a unique constraint on oauthRefreshToken.token for parity with oauthAccessToken.token.

Patches

Fixed in @better-auth/oauth-provider@1.6.11. The refresh-token rotation primitive now performs an atomic compare-and-swap on the parent row, and the explicit revokeRefreshToken path uses the same CAS. On a contested rotation, exactly one caller wins and mints a fresh refresh token; the loser receives invalid_grant. Subsequent replay of the original refresh token trips the existing family-invalidation guard because the parent row stays marked revoked.

@better-auth/memory-adapter@1.6.11 ships a compatibility fix in the same wave: the in-memory where clause now treats undefined and null as equivalent under an eq null predicate, mirroring SQL IS NULL and Mongo's missing-or-null semantics. Without this change, the CAS predicate WHERE revoked IS NULL falls through on every call against a row whose optional revoked field is absent (the adapter factory's transformInput skips writing undefined when no default exists), so the rotation above is broken for any deployment using the in-memory adapter.

Strict refresh-token family invalidation on a contested rotation, per RFC 9700 §4.14 (which calls for invalidating the winner's tokens too when reuse is detected at rotation time), is deferred to a follow-up minor on the next channel. Closing it cleanly requires an opt-in transactional rotation in the adapter contract so the family-delete cannot interleave with the winner's in-flight access-token insert. The deferred site carries a FIXME(strict-family-invalidation) marker.

Schema-migration note: the better-auth migration generator only emits UNIQUE for newly-created columns. Existing installs will not pick up the new oauthRefreshToken.token unique constraint from migrate / generate; add it manually if an application's operational tooling depends on it (CREATE UNIQUE INDEX oauth_refresh_token_token_uniq ON "oauthRefreshToken" (token);). The CAS fix above does not depend on the database-level constraint to be correct; the constraint is defense-in-depth so collisions from a buggy custom generateRefreshToken callback fail loudly.

Workarounds

None of these close the bug fully without a code patch.

  • Adapter-level: configure the database adapter to run the OAuth refresh handler under serializable isolation, or wrap the adapter.update on oauthRefreshToken with a row-level pessimistic lock (SELECT ... FOR UPDATE). Narrows the window without closing it.
  • Token lifetime: pass oauthProvider({ refreshTokenExpiresIn: 60 }) to expire forked families within one minute. Trades attacker persistence for shorter user sessions.
  • Client-side single-flight: serialize refresh-token usage in the client SDK with a mutex. Mitigates honest concurrency but does nothing against an attacker with a stolen refresh token.
  • Disable refresh tokens: do not request the offline_access scope. Closes the surface but breaks long-lived sessions.

Impact

  • Indefinite access from a single stolen refresh token: forked refresh-token families grant access at the original user's authorization scope, surviving past any single revocation if an attacker holds any branch.
  • Detection bypass: legitimate users whose refresh token has been forked do not trip family invalidation when they refresh, because the attacker's branch already swapped the parent row out from under the legitimate user's check.

Credit

Reported by @chdanielmueller.

Resources

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@better-auth/oauth-provider"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.6.0"
            },
            {
              "fixed": "1.6.11"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "better-auth"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.4.8-beta.7"
            },
            {
              "fixed": "1.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-53517"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-294",
      "CWE-362",
      "CWE-367",
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-07T20:55:48Z",
    "nvd_published_at": "2026-07-15T18:16:48Z",
    "severity": "HIGH"
  },
  "details": "### Am I affected?\n\nUsers are affected if all of the following are true:\n\n- Their project depends on `@better-auth/oauth-provider` at a version `\u003e= 1.6.0, \u003c 1.6.11`, or uses the embedded plugin in `better-auth \u003e= 1.4.8-beta.7, \u003c 1.6.0`.\n- At least one OAuth client served by their application\u0027s authorization server requests the `offline_access` scope, so refresh tokens are minted.\n- Concurrent redemption of the same refresh token is reachable: an SPA shares one refresh token across browser tabs without a mutex, a mobile client retries after a transient failure, an attacker who has stolen a refresh token times two requests, or a service worker queues offline requests.\n\nIf developer applications do not request `offline_access` for any client, no refresh tokens are minted and they are not exposed.\n\nFix:\n\n1. Upgrade to `@better-auth/oauth-provider@1.6.11` or later.\n2. If developers cannot upgrade, see workarounds below.\n\n### Summary\n\nThe OAuth provider\u0027s `POST /oauth2/token` endpoint, on the `refresh_token` grant, performs a non-atomic read / validate / revoke / mint sequence on the `oauthRefreshToken` row. Two concurrent requests presenting the same parent refresh token both pass the revocation check before either revoke completes, so each mints a fresh refresh token. The replay-detection branch only fires when `revoked` is already truthy at read time, which is exactly the state concurrent attackers race past. The result is a forked refresh-token family from a single parent token.\n\n### Details\n\nThe `adapter.update` predicate on the parent row is keyed on `id` only; it does not include `revoked IS NULL`, so two concurrent updates both succeed (last-write-wins, no error path). The schema does not declare `unique` on `oauthRefreshToken.token`, so concurrent creates do not collide on a unique-key violation either.\n\nRFC 9700 \u00a74.14 (OAuth Security Best Current Practice) prescribes refresh-token family invalidation on detected reuse; this implementation tries to enforce that contract through the `revoked` check, but the check is not atomic with the consumption step. Token rotation issues a new refresh token with each call, so a single stolen refresh token grants indefinite access until the row is revoked or its `refreshTokenExpiresAt` (default 7 days) passes. Rotation refreshes that window each call.\n\nThe fix lands an atomic compare-and-swap on the parent row inside the rotation primitive (`UPDATE ... WHERE id = ? AND revoked IS NULL` with a rowcount check), so the losing rotation fails closed with `invalid_grant` and the parent row stays marked revoked. Subsequent replay of the original refresh token then trips the existing family-invalidation guard. The schema gains a unique constraint on `oauthRefreshToken.token` for parity with `oauthAccessToken.token`.\n\n### Patches\n\nFixed in `@better-auth/oauth-provider@1.6.11`. The refresh-token rotation primitive now performs an atomic compare-and-swap on the parent row, and the explicit `revokeRefreshToken` path uses the same CAS. On a contested rotation, exactly one caller wins and mints a fresh refresh token; the loser receives `invalid_grant`. Subsequent replay of the original refresh token trips the existing family-invalidation guard because the parent row stays marked revoked.\n\n`@better-auth/memory-adapter@1.6.11` ships a compatibility fix in the same wave: the in-memory `where` clause now treats `undefined` and `null` as equivalent under an `eq null` predicate, mirroring SQL `IS NULL` and Mongo\u0027s missing-or-null semantics. Without this change, the CAS predicate `WHERE revoked IS NULL` falls through on every call against a row whose optional `revoked` field is absent (the adapter factory\u0027s `transformInput` skips writing `undefined` when no default exists), so the rotation above is broken for any deployment using the in-memory adapter.\n\nStrict refresh-token family invalidation on a contested rotation, per RFC 9700 \u00a74.14 (which calls for invalidating the winner\u0027s tokens too when reuse is detected at rotation time), is deferred to a follow-up minor on the `next` channel. Closing it cleanly requires an opt-in transactional rotation in the adapter contract so the family-delete cannot interleave with the winner\u0027s in-flight access-token insert. The deferred site carries a `FIXME(strict-family-invalidation)` marker.\n\nSchema-migration note: the better-auth migration generator only emits `UNIQUE` for newly-created columns. Existing installs will not pick up the new `oauthRefreshToken.token` unique constraint from `migrate` / `generate`; add it manually if an application\u0027s operational tooling depends on it (`CREATE UNIQUE INDEX oauth_refresh_token_token_uniq ON \"oauthRefreshToken\" (token);`). The CAS fix above does not depend on the database-level constraint to be correct; the constraint is defense-in-depth so collisions from a buggy custom `generateRefreshToken` callback fail loudly.\n\n### Workarounds\n\nNone of these close the bug fully without a code patch.\n\n- **Adapter-level**: configure the database adapter to run the OAuth refresh handler under serializable isolation, or wrap the `adapter.update` on `oauthRefreshToken` with a row-level pessimistic lock (`SELECT ... FOR UPDATE`). Narrows the window without closing it.\n- **Token lifetime**: pass `oauthProvider({ refreshTokenExpiresIn: 60 })` to expire forked families within one minute. Trades attacker persistence for shorter user sessions.\n- **Client-side single-flight**: serialize refresh-token usage in the client SDK with a mutex. Mitigates honest concurrency but does nothing against an attacker with a stolen refresh token.\n- **Disable refresh tokens**: do not request the `offline_access` scope. Closes the surface but breaks long-lived sessions.\n\n### Impact\n\n- **Indefinite access from a single stolen refresh token**: forked refresh-token families grant access at the original user\u0027s authorization scope, surviving past any single revocation if an attacker holds any branch.\n- **Detection bypass**: legitimate users whose refresh token has been forked do not trip family invalidation when they refresh, because the attacker\u0027s branch already swapped the parent row out from under the legitimate user\u0027s check.\n\n### Credit\n\nReported by @chdanielmueller.\n\n### Resources\n\n- [CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition)](https://cwe.mitre.org/data/definitions/362.html)\n- [CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition](https://cwe.mitre.org/data/definitions/367.html)\n- [CWE-294: Authentication Bypass by Capture-replay](https://cwe.mitre.org/data/definitions/294.html)\n- [CWE-613: Insufficient Session Expiration](https://cwe.mitre.org/data/definitions/613.html)\n- [RFC 9700 \u00a74.14: Refresh Token Protection](https://datatracker.ietf.org/doc/html/rfc9700#section-4.14)\n- [RFC 6749 \u00a76: Refreshing an Access Token](https://datatracker.ietf.org/doc/html/rfc6749#section-6)",
  "id": "GHSA-392p-2q2v-4372",
  "modified": "2026-07-20T19:24:47Z",
  "published": "2026-07-07T20:55:48Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/better-auth/better-auth/security/advisories/GHSA-392p-2q2v-4372"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53517"
    },
    {
      "type": "WEB",
      "url": "https://github.com/better-auth/better-auth/commit/c6918ecc9e3a75892169415d7f6c95b591b6a52d"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/better-auth/better-auth"
    },
    {
      "type": "WEB",
      "url": "https://github.com/better-auth/better-auth/releases/tag/v1.6.0"
    },
    {
      "type": "WEB",
      "url": "https://github.com/better-auth/better-auth/releases/tag/v1.6.11"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Better Auth: OAuth refresh-token rotation forks the token family on concurrent redemption"
}

Mitigation
Implementation

Set sessions/credentials expiration date.

No CAPEC attack patterns related to this CWE.