Penetration Testing

Password Reset Bypass: The Test Case to Demand

Two 2026 CVEs show one authentication class: a flow that finishes without the step that proves identity. The test case to demand in your pentest scope.

RG&AK
Rathnakara GN & Ashok Kamat
Cybersecify
12 min read

Two authentication CVEs published in 2026 look unrelated until you line up the root causes. In Keycloak, a password reset could be completed without the user ever following the emailed verification link. In Supabase Auth, a session could be issued for someone else’s account because the server accepted an ID token without confirming who had issued it. Neither is a cryptography failure and neither is exotic. Both are the same class: an authentication flow that reaches its final state without performing the one check that establishes identity. That class has a name and a test case in the methodology we run on every web engagement, which makes it something you can put in a scope document and ask a vendor about by identifier.

Key findings

  • The class is a flow that finishes without the step that proves identity, not a broken algorithm. Everything else in both flows validated correctly. The missing check was the one that answered who the request belonged to.
  • CVE-2026-18963 in Keycloak carries a CVSS v3.1 base score of 9.1 and CWE-640. Red Hat, as the CVE Numbering Authority, describes the root cause as improper state validation within the reset-credentials authentication flow.
  • The matching test case is WSTG-ATHN-09 in OWASP WSTG v4.2, Testing for Weak Password Change or Reset Functionalities, and the guide’s own requirement is the exact control the CVE bypasses: the reset completes only if the user visits the emailed link.
  • CVE-2026-31813 in Supabase Auth is the same class one layer over, mapped to WSTG-ATHN-04 and CWE-290, where the server checked that an ID token was validly signed but not that the expected provider had signed it.
  • Coverage is the only honest promise here. Running the test case is not a guarantee of finding every instance, but a scope that omits reset flow testing cannot find it at all.

This post is written from the published record. We did not test Keycloak, Supabase, or any deployment of either, and nothing here describes a live weakness or contains reproduction detail. Both issues are fixed in the versions named below. The technique is kept at the level a defender needs in order to recognise the same shape in their own product.

The class, stated plainly

Every authentication flow is a sequence of steps that ends by granting something: a session, a token, a new password. Somewhere in that sequence there is exactly one step that answers the question the whole flow exists to answer, which is whether the person driving it is the account holder.

In a password reset, that step is possession of the registered mailbox, demonstrated by visiting a link only the mailbox owner could have received. In a federated login, it is the identity of the party that signed the assertion. In an invite acceptance, it is possession of the invite. In an email change, it is confirmation at the new address, the old one, or both.

The class of bug is what happens when the flow can reach its end state without that step having actually gated anything. It is not that the step is missing from the product. In both CVEs below the step existed, was documented, and worked when followed. The failure was that the flow did not refuse to continue when the step was skipped.

That distinction is why this class is hard to see in a design review and easy to see in a test. On a diagram, the arrow from step two to step three looks like a dependency. In the running system, whether it is a dependency or a suggestion is a question about code, and the only reliable way to answer it is to try to take step three without step two.

Keycloak is a widely deployed open source identity and access management server. CVE-2026-18963 affects its reset-credentials flow in the keycloak-services component.

Red Hat, which issued the record as the CVE Numbering Authority, describes the flaw as one that “allows an unauthenticated attacker to force the password reset process for any user without needing to click the required email verification link.” The base score is CVSS v3.1 9.1, vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, and Red Hat’s product security team rates the severity as Critical. The weakness is classified as CWE-640, Weak Password Recovery Mechanism for Forgotten Password.

The sentence to sit with is Red Hat’s own statement of cause: “The vulnerability’s root cause is improper state validation within the reset-credentials authentication flow.” Not a weak token. Not a predictable secret. Not an email that went to the wrong place. The state machine did not enforce its own ordering.

Upstream Keycloak 26.7.2, released 19 August 2026, lists the fix in its release notes as “[CVE-2026-18963] Unauthenticated account takeover via reset-credentials flow bypass”. For the Red Hat build of Keycloak, the fix shipped on 18 August 2026 in 26.4.15 and 26.6.6, under advisories RHSA-2026:56520 and RHSA-2026:56524. Where an immediate upgrade was not possible, Red Hat’s documented interim mitigation was to disable the Forgot password functionality across all realms.

On 7 September 2026, three weeks after the fix shipped, India’s national CERT published its own note on this vulnerability: CERT-In Vulnerability Note CIVN-2026-0442, rated CRITICAL, describing the cause as improper state validation within the reset-credentials authentication flow. Its affected-version list makes the same split as above, naming upstream Keycloak prior to 26.7.2 separately from Red Hat build 26.4 prior to 26.4.15 and 26.6 prior to 26.6.6. If you sell into an Indian regulated entity, that is the reference their security team is most likely to be working from.

Read that mitigation again, because it says something useful about the class. The recommended stopgap was to turn the feature off. There was no configuration that made the flow safe while leaving it enabled, which is what it looks like when the control lives in the flow’s own logic rather than in a setting.

Evidence two: a session issued to whoever signed the token

CVE-2026-31813, tracked as GHSA-v36f-qvww-8w8m, affects Supabase Auth in all versions prior to 2.185.0 and is fixed in 2.185.0. The advisory title is “Insecure Apple and Azure authentication with ID tokens”, and the issue applies when the Apple or Azure providers are enabled.

The published description is precise about the mechanism. An attacker issues a valid, asymmetrically signed ID token from their own issuer for a victim’s email address and presents it through the ID token flow. If the token is OIDC compliant, the server validates it against the attacker controlled issuer, links the victim’s existing OIDC identity to an additional identity derived from the token contents, and then issues a valid user session, access and refresh tokens, at the AAL1 level.

The token was well formed. The signature was genuine. The flow checked that the assertion was internally consistent and never checked that it had come from the provider the project had configured. That is CWE-290, and it is the same shape as the Keycloak issue viewed from a different angle: the step that establishes identity is present in the design and not enforced as a condition of finishing.

Two things about this one are worth keeping in proportion. It scores CVSS v3.1 4.8, Medium, on both the NVD assessment and the assessment from GitHub as CNA, with attack complexity rated High, because the attacker needs an issuer of their own and a target email address. It is a smaller number than the Keycloak score and it is still full session issuance for an arbitrary account. Severity scores are a triage aid, not a description of what the bug does.

Where this sits in the methodology

Both issues map to named test cases in OWASP WSTG v4.2, which is the guide our web application testing follows and the one whose identifiers appear in our sample report beside each finding.

EvidenceTest caseTop 10 categoryWeakness
Keycloak CVE-2026-18963WSTG-ATHN-09, Testing for Weak Password Change or Reset FunctionalitiesA07:2025 Authentication FailuresCWE-640
Supabase Auth CVE-2026-31813WSTG-ATHN-04, Testing for Bypassing Authentication SchemaA07:2025 Authentication FailuresCWE-290
The same classes on an API surfaceAPI2:2023 Broken AuthenticationOWASP API Security Top 10 2023Varies by instance

The reason WSTG-ATHN-09 is the right anchor for the Keycloak case is that the guide states the control the CVE bypasses, in its own words: “the application should email a link to the user with a random token, and only if the user visits the link then the reset procedure is completed. This ensures that the current password will still be valid until the reset has been confirmed.”

That is not a paraphrase written after the fact to fit an incident. It is a requirement published in a guide from 2020, describing the precise property that failed in 2026. The test case exists because this class of failure was already understood. What varies between products is whether anyone checked.

WSTG-ATHN-04 covers the second case for a similar reason. The guide notes that “it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated”. An ID token from an issuer the application never agreed to trust is a fairly exact instance of that sentence.

Where the same flows sit behind an API rather than a browser, the API Security Top 10 2023 item API2:2023 Broken Authentication is the category, and the practical difficulty shifts from finding the flow to finding all of them, which is a scoping problem we have written about separately in the authentication problem in API pentests.

What to check in your own product

None of this requires knowing anything about how Keycloak or Supabase is built. Work through it in order, on your own system.

1. List every path that ends in a credential change or a session. Login is the obvious one and it is rarely the problem, because it gets attention. The list that matters is the rest: password reset, invite acceptance, email address change, phone number change, magic link, social or SSO login, account linking, device enrolment, API key rotation, support driven account recovery, and any impersonation feature built for the support team. Most teams find between eight and fifteen. Most teams have tested one.

2. For each path, name the fact that proves identity. One sentence, written down. Possession of the registered mailbox. Possession of the invite. A signature from the specific identity provider we configured. The current password. A registered second factor. If nobody on the team can state the fact for a given path in one sentence, that path is the first one to test.

3. Find the line of code that refuses to continue when the fact is missing. This is the step that separates a design from a control. The fact being checked earlier in the flow is not enough, because the question is whether the final step verifies that the earlier check actually happened for this specific request, or merely assumes it did. In both CVEs above, the earlier step existed. What was missing was the refusal at the end.

4. Check what carries the state between steps. Multi step flows keep their progress somewhere: a server side session, a signed cookie, a database row, a value in the request. Whatever it is, ask two questions about it. Can the client influence it, and does the final step verify it belongs to this flow, this user and this attempt. Improper state validation is the phrase Red Hat used, and state is the thing multi step authentication flows are made of.

5. Confirm the identity of every party you trust, not just the validity of what they sent. Any assertion from outside your system carries two separate questions: is this well formed and correctly signed, and did the specific party we intended to trust sign it. Answering the first and skipping the second is the Supabase case. In OIDC terms this is issuer validation against a configured value rather than against whatever the token names. The same reasoning applies to webhooks, SAML assertions, and any callback that arrives with a signature.

6. Know your version and your update path. Both of these were fixed by a vendor. The gap between a fix existing and a fix being deployed is a schedule problem, not a security research problem, and it is the part of this that a CTO owns directly. If you cannot answer today which minor version of your identity provider is running in production, that answer is the finding.

What to ask a pentest vendor

This is the part that survives the specific CVEs. Both records will age. The question a buyer can ask will not.

Ask whether the engagement tests that a password reset cannot be completed without the emailed token, and ask to be shown where that sits in the scope. A vendor who runs the OWASP WSTG can answer with an identifier, WSTG-ATHN-09, and can point at the section of a delivered report where a test case identifier appears next to a finding. A vendor who cannot will answer with an adjective.

Then ask the same question about the other flows on your list from step one. Invite acceptance and email change are the two most often missing, because they are built by the product team rather than the auth team and they look like features rather than authentication.

Be precise about what a yes buys you. Running the test case is not a guarantee of finding every instance of this class, but a scope that omits reset flow testing cannot find it at all. That is a claim about coverage, and coverage is the only thing a scope can honestly promise. Anyone who upgrades it into a promise about outcomes has told you something useful about how they will handle the rest of the engagement.

The corresponding thing to ask for in the deliverable is that each finding names the test case it came from, so that you can check the work against the methodology rather than taking a list on trust. That is how our sample report is structured, and it is a reasonable thing to require of anyone.

Scope and timeline

Authentication flow testing sits inside an application scope rather than beside it, so it is not a separate purchase and it does not extend the engagement. On our engagements one scope is five business days, and scopes run sequentially by default, so two scopes are ten business days. Parallel testing is available on request on the Growth plan from the third scope onward, and it is an option rather than a guarantee.

The Startup plan at INR 74,999 covers one scope, and the Growth plan at INR 1,79,999 covers two along with SOC 2 and ISO 27001 evidence mapping. Both include one free retest. Full detail on how we test is on the methodology page.

The scoping conversation worth having is not whether authentication is included. It is which flows are named in the scope document. A scope that says “the web application” and a scope that says “the web application including password reset, invite acceptance, email change and the SSO login path” describe the same product and buy different work. Write the second one.

Corrections

  • 2026-09-07: Added CERT-In Vulnerability Note CIVN-2026-0442, published two days after this article, which covers the same Keycloak flaw and corroborates the upstream-versus-Red-Hat version split stated here.

Key takeaways, in one page

A single-page summary of this article. Free to share, repost or put in a deck. We only ask that the link stays on it.

One-page key takeaways from Password Reset Bypass: The Test Case to Demand

Frequently Asked Questions

What is the vulnerability class these two CVEs share?

An authentication flow that reaches its final state without performing the one check that establishes who the user is. Every other check in the flow can pass. The token can be well formed, the signature can be valid, the request can arrive in the right order, and the account can still be handed to the wrong person, because the step that proves identity was never enforced as a condition of finishing. In a password reset, that step is possession of the registered mailbox, demonstrated by visiting the emailed link. In a federated login, it is the identity of the issuer that signed the token. Both are cheap to skip and expensive to miss, because neither absence produces an error a user or a monitoring dashboard would notice.

What is WSTG-ATHN-09 and why does it matter to a buyer?

WSTG-ATHN-09 is the OWASP Web Security Testing Guide v4.2 test case called Testing for Weak Password Change or Reset Functionalities. It matters to a buyer because it is a named, checkable unit of work. You can ask a vendor whether it is in the scope of your engagement, and you can ask them to show you where the identifier appears in a report they have already delivered. A vendor who tests the reset flow will have the identifier somewhere. A vendor who does not will describe the coverage in adjectives instead.

Does running the test case guarantee this class gets found?

No, and any vendor who says otherwise is selling you something we cannot sell. Running the test case is not a guarantee of finding every instance, but a scope that omits reset flow testing cannot find it at all. That is the honest shape of the claim. Coverage is what a scope can promise. Outcome is not, and the difference is worth insisting on when you read a proposal, because a proposal that promises outcomes is either misunderstanding the work or hoping you will not check.

Was CVE-2026-18963 a flaw in Keycloak's cryptography?

No. Red Hat, as the CVE Numbering Authority, states the root cause as improper state validation within the reset-credentials authentication flow. Nothing was wrong with the token generation or the email delivery. The flow simply allowed the process to progress past the point where the emailed verification link was meant to gate it. This is why the fix is a state check rather than a stronger secret, and why looking for this class with a cryptographic lens finds nothing.

We use a managed identity provider. Are we out of scope for this?

No. Both of the 2026 examples here are managed or packaged identity products rather than hand written login code, which is the point worth taking away. Keycloak is a widely deployed open source identity and access management server, and Supabase Auth is a hosted authentication service. Buying identity moves the code out of your repository. It does not move the authentication flow out of your attack surface, and it does not remove your obligation to know which version you are running and how quickly you can update it.

How does this fit into a pentest scope and timeline?

Authentication flow testing belongs inside the application scope rather than beside it, so it does not add a line item. One scope is five business days on our engagements, and scopes run sequentially by default, so two scopes are ten business days. The practical scoping question is not whether authentication is included but whether the reset, invite, email change and federated login flows are named in the scope document alongside the login form, because those are the paths most often assumed to be covered and least often written down.

What should we check in our own code this week?

List every path that can produce an authenticated session or change a credential, then for each one write down the single fact that proves the person is who they claim to be and the line of code that refuses to continue when that fact is missing. Most teams can name the fact immediately. The gap is usually the refusal. If you cannot point at the line that stops the flow, the flow does not stop.

Security questions, worries, or not sure what to use?

Cybersecify is a founder-led penetration testing firm for AI and SaaS startups. Tell us what you are weighing and we will give you a straight answer. Ask the team or book a free 30-minute call.

Share this article
Authentication TestingOWASP WSTGPassword ResetAccount TakeoverPenetration TestingPentest Scoping

Spotted something wrong on this page? Facts change and we get things wrong. Tell us and we will check it. We publish corrections on the page rather than editing quietly.