CVE-2026-72711
Full vulnerability record from the local CVENow database.
Description
The Lean 4 kernel does not check that the body of an opaque declaration is closed. environment::add_opaque omits the check_no_metavar_no_fvar call that the definition and theorem paths perform, so a value containing a free variable that is absent from the local context is not rejected outright. A metaprogram can first cause the kernel to create a temporary local of type False and record its type in the type checker's inference cache, then restore the local context while that cache entry persists on the same type checker instance, and finally submit an opaque declaration whose value is the now-unbound variable. The cache lookup answers before the branch that would test membership of the local context, so the kernel infers the cached type and admits an opaque constant of type False, from which any proposition follows. The declaration is accepted through the ordinary checked path at maximum kernel checking, without sorry, unsafeCast, debug.skipKernelTC, addDeclWithoutChecking, foreign code or a modified .olean file, and the result carries no axioms. Fixed in 4.32.2 by adding the missing closure check.
View original CVE JSON
{
"id": "CVE-2026-72711",
"sourceIdentifier": "[email protected]",
"published": "2026-08-24T20:17:18.657",
"lastModified": "2026-10-26T02:17:07.503",
"vulnStatus": "Deferred",
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "The Lean 4 kernel does not check that the body of an opaque declaration is closed. environment::add_opaque omits the check_no_metavar_no_fvar call that the definition and theorem paths perform, so a value containing a free variable that is absent from the local context is not rejected outright. A metaprogram can first cause the kernel to create a temporary local of type False and record its type in the type checker's inference cache, then restore the local context while that cache entry persists on the same type checker instance, and finally submit an opaque declaration whose value is the now-unbound variable. The cache lookup answers before the branch that would test membership of the local context, so the kernel infers the cached type and admits an opaque constant of type False, from which any proposition follows. The declaration is accepted through the ordinary checked path at maximum kernel checking, without sorry, unsafeCast, debug.skipKernelTC, addDeclWithoutChecking, foreign code or a modified .olean file, and the result carries no axioms. Fixed in 4.32.2 by adding the missing closure check."
},
{
"lang": "es",
"value": "El kernel de Lean 4 no verifica que el cuerpo de una declaración opaca esté cerrado. environment::add_opaque omite la llamada a check_no_metavar_no_fvar que realizan las rutas de definición y teorema, por lo que un valor que contiene una variable libre que está ausente del contexto local no es rechazado de inmediato. Un metaprograma puede primero hacer que el kernel cree una variable local temporal de tipo False y registre su tipo en la caché de inferencia del verificador de tipos, luego restaurar el contexto local mientras esa entrada de caché persiste en la misma instancia del verificador de tipos, y finalmente enviar una declaración opaca cuyo valor es la variable ahora desvinculada. La búsqueda en caché responde antes de la rama que probaría la pertenencia al contexto local, por lo que el kernel infiere el tipo en caché y admite una constante opaca de tipo False, de la cual se sigue cualquier proposición. La declaración es aceptada a través de la ruta verificada ordinaria con la máxima verificación del kernel, sin sorry, unsafeCast, debug.skipKernelTC, addDeclWithoutChecking, código externo o un archivo .olean modificado, y el resultado no conlleva axiomas. Corregido en 4.32.2 al añadir la verificación de cierre faltante."
}
],
"affected": [
{
"source": "[email protected]",
"affectedData": [
{
"vendor": "leanprover",
"product": "lean4",
"defaultStatus": "unaffected",
"repo": "https://github.com/leanprover/lean4",
"packageURL": "pkg:github/leanprover/lean4",
"versions": [
{
"version": "0",
"lessThan": "4.32.2",
"versionType": "semver",
"status": "affected"
}
]
}
]
}
],
"metrics": {
"cvssMetricV40": [
{
"source": "[email protected]",
"type": "Secondary",
"cvssData": {
"version": "4.0",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/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": 6.8,
"baseSeverity": "MEDIUM",
"attackVector": "LOCAL",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"privilegesRequired": "NONE",
"userInteraction": "PASSIVE",
"vulnConfidentialityImpact": "NONE",
"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": "Secondary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N",
"baseScore": 6.3,
"baseSeverity": "MEDIUM",
"attackVector": "LOCAL",
"attackComplexity": "LOW",
"privilegesRequired": "NONE",
"userInteraction": "REQUIRED",
"scope": "CHANGED",
"confidentialityImpact": "NONE",
"integrityImpact": "HIGH",
"availabilityImpact": "NONE"
},
"exploitabilityScore": 1.8,
"impactScore": 4.0
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"timestamp": "2026-08-24T20:14:31.474084Z",
"id": "CVE-2026-72711",
"options": [
{
"exploitation": "poc"
},
{
"automatable": "no"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"version": "2.0.3"
}
}
]
},
"weaknesses": [
{
"source": "[email protected]",
"type": "Secondary",
"description": [
{
"lang": "en",
"value": "CWE-20"
}
]
}
],
"references": [
{
"url": "https://github.com/endrazine/lean-cve-poc-14484",
"source": "[email protected]"
},
{
"url": "https://github.com/leanprover/lean4",
"source": "[email protected]"
},
{
"url": "https://github.com/leanprover/lean4/issues/14484",
"source": "[email protected]"
},
{
"url": "https://github.com/leanprover/lean4/pull/14498",
"source": "[email protected]"
},
{
"url": "https://www.vulncheck.com/advisories/lean-4-before-kernel-accepts-opaque-declaration-with-an-unbound-free-variable",
"source": "[email protected]"
},
{
"url": "http://www.openwall.com/lists/oss-security/2026/10/26/3",
"source": "af854a3a-2127-422b-91ae-364da2661108"
}
]
}