CVE-2018-0995
Description
A memory corruption vulnerability in ChakraCore and Microsoft Edge allows remote code execution via crafted JavaScript.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A memory corruption vulnerability in ChakraCore and Microsoft Edge allows remote code execution via crafted JavaScript.
Vulnerability
A remote code execution vulnerability exists in the way that the Chakra scripting engine handles objects in memory in Microsoft Edge, also known as a Chakra Scripting Engine Memory Corruption Vulnerability [1]. This issue affects Microsoft Edge and ChakraCore [1]. The vulnerability is a memory corruption flaw that occurs when the engine processes specially crafted JavaScript code, specifically during the conversion of JavascriptNativeIntArray to a Var array, as seen in the patch that moves the fill operation before the segment replacement to prevent use-after-free [2]. Affected versions include ChakraCore and Microsoft Edge on impacted Windows platforms [3].
Exploitation
An attacker can exploit this vulnerability by hosting a specially crafted website (or leveraging a compromised site) that contains malicious JavaScript code, then convincing a user to visit that site in Microsoft Edge, or by embedding the code in an application that uses ChakraCore [1][3]. No authentication is required. The user interaction is limited to visiting the malicious page. The vulnerability lies in the failure to handle exceptional conditions, specifically a timing issue during array conversion that leads to memory corruption [2][3].
Impact
Successful exploitation allows an attacker to execute arbitrary code in the context of the current user [1]. If the user has administrative privileges, the attacker can gain complete control of the system, install programs, view/change/delete data, or create new accounts [1]. The attacker achieves remote code execution (RCE) with the privilege level of the victim user [1].
Mitigation
Microsoft released security updates on April 10, 2018, to address this vulnerability [3]. For ChakraCore, the fix is included in commit 396d78f60a3d8444218253523365965f97942225 [2]. Users should apply the latest updates from Microsoft Update or Windows Update [3]. For ChakraCore, updating to a version that includes the fix is necessary [2]. The vulnerability is not listed as KEV (Known Exploited Vulnerabilities) catalog.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
Microsoft.ChakraCoreNuGet | < 1.8.3 | 1.8.3 |
Affected products
3- Range: ChakraCore
Patches
1396d78f60a3d[CVE-2018-0995] Edge - JavascriptNativeIntArray::ConvertToVarArray could lead to UAF - Individual
1 file changed · +39 −31
lib/Runtime/Library/JavascriptArray.cpp+39 −31 modified@@ -1921,8 +1921,21 @@ namespace Js // And/or the old segment is not scanned by the recycler, so we need a new one to hold vars. SparseArraySegment<Var> *newSeg = SparseArraySegment<Var>::AllocateSegment(recycler, left, length, nextSeg); - AnalysisAssert(newSeg); + + // Fill the new segment with the overflow. + for (i = 0; (uint)i < newSeg->length; i++) + { + ival = ((SparseArraySegment<int32>*)seg)->elements[i]; + if (ival == JavascriptNativeIntArray::MissingItem) + { + continue; + } + newSeg->elements[i] = JavascriptNumber::ToVar(ival, scriptContext); + } + + // seg elements are copied over, now it is safe to replace seg with newSeg. + // seg could be GC collected if replaced by newSeg. Assert((prevSeg == nullptr) == (seg == intArray->head)); newSeg->next = nextSeg; intArray->LinkSegments((SparseArraySegment<Var>*)prevSeg, newSeg); @@ -1937,17 +1950,6 @@ namespace Js { segmentMap->SwapSegment(left, seg, newSeg); } - - // Fill the new segment with the overflow. - for (i = 0; (uint)i < newSeg->length; i++) - { - ival = ((SparseArraySegment<int32>*)seg)->elements[i]; - if (ival == JavascriptNativeIntArray::MissingItem) - { - continue; - } - newSeg->elements[i] = JavascriptNumber::ToVar(ival, scriptContext); - } } else { @@ -2097,26 +2099,12 @@ namespace Js } uint32 left = seg->left; uint32 length = seg->length; - SparseArraySegment<Var> *newSeg; + SparseArraySegment<Var> *newSeg = nullptr; if (seg->next == nullptr && SparseArraySegmentBase::IsLeafSegment(seg, recycler)) { // The old segment is not scanned by the recycler, so we need a new one to hold vars. newSeg = SparseArraySegment<Var>::AllocateSegment(recycler, left, length, nextSeg); - Assert((prevSeg == nullptr) == (seg == fArray->head)); - newSeg->next = nextSeg; - fArray->LinkSegments((SparseArraySegment<Var>*)prevSeg, newSeg); - if (fArray->GetLastUsedSegment() == seg) - { - fArray->SetLastUsedSegment(newSeg); - } - prevSeg = newSeg; - - SegmentBTree * segmentMap = fArray->GetSegmentMap(); - if (segmentMap) - { - segmentMap->SwapSegment(left, seg, newSeg); - } } else { @@ -2172,6 +2160,26 @@ namespace Js // Fill the remaining slots. newSeg->FillSegmentBuffer(i, seg->size); } + + // seg elements are copied over, now it is safe to replace seg with newSeg. + // seg could be GC collected if replaced by newSeg. + if (newSeg != seg) + { + Assert((prevSeg == nullptr) == (seg == fArray->head)); + newSeg->next = nextSeg; + fArray->LinkSegments((SparseArraySegment<Var>*)prevSeg, newSeg); + if (fArray->GetLastUsedSegment() == seg) + { + fArray->SetLastUsedSegment(newSeg); + } + prevSeg = newSeg; + + SegmentBTree * segmentMap = fArray->GetSegmentMap(); + if (segmentMap) + { + segmentMap->SwapSegment(left, seg, newSeg); + } + } } if (fArray->GetType() == scriptContext->GetLibrary()->GetNativeFloatArrayType()) @@ -3140,7 +3148,7 @@ namespace Js JS_REENTRANT_NO_MUTATE(jsReentLock, CopyNativeIntArrayElementsToVar(pDestArray, BigIndex(idxDest).GetSmallIndex(), pIntItemArray)); idxDest = idxDest + pIntItemArray->length; } - else + else { JavascriptNativeFloatArray *pFloatItemArray = JavascriptOperators::TryFromVar<JavascriptNativeFloatArray>(aItem); if (pFloatItemArray) @@ -3390,7 +3398,7 @@ namespace Js idxDest = idxDest + pIntItemArray->length; } - else + else { JavascriptNativeFloatArray * pFloatItemArray = JavascriptOperators::TryFromVar<JavascriptNativeFloatArray>(aItem); if (pFloatItemArray && !isFillFromPrototypes) @@ -5384,7 +5392,7 @@ namespace Js { RecyclableObject* protoObj = prototype; - if (!(DynamicObject::IsAnyArray(protoObj) || JavascriptOperators::IsObject(protoObj)) + if (!(DynamicObject::IsAnyArray(protoObj) || JavascriptOperators::IsObject(protoObj)) || JavascriptProxy::Is(protoObj) || protoObj->IsExternal()) { @@ -6099,7 +6107,7 @@ namespace Js *isIntArray = true; #endif } - else + else { JavascriptNativeFloatArray* nativeFloatArray = JavascriptOperators::TryFromVar<JavascriptNativeFloatArray>(this); if (nativeFloatArray)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-c6mx-gwgr-mfm2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-0995ghsaADVISORY
- www.securityfocus.com/bid/103631mitrevdb-entryx_refsource_BID
- www.securitytracker.com/id/1040650mitrevdb-entryx_refsource_SECTRACK
- github.com/chakra-core/ChakraCore/commit/396d78f60a3d8444218253523365965f97942225ghsaWEB
- portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-0995ghsax_refsource_CONFIRMWEB
- web.archive.org/web/20210125210155/http://www.securityfocus.com/bid/103631ghsaWEB
- web.archive.org/web/20211207123630/http://www.securitytracker.com/id/1040650ghsaWEB
News mentions
0No linked articles in our index yet.