CVE-2018-8367
Description
A memory corruption vulnerability in the Chakra scripting engine in Microsoft Edge and ChakraCore allows remote code execution via specially crafted web content.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A memory corruption vulnerability in the Chakra scripting engine in Microsoft Edge and ChakraCore allows remote code execution via specially crafted web content.
Vulnerability
CVE-2018-8367 is a remote code execution vulnerability in the Chakra scripting engine that affects Microsoft Edge and ChakraCore. The bug is a use-after-free (UAF) flaw in the InitBoxedInlineSegments method of JavascriptArray, where memory is improperly handled when copying inline segment data for arrays [3]. The vulnerable code does not correctly handle the case where the head segment is inline, leading to a memory corruption that can be triggered during script execution. Affected versions include Microsoft Edge on Windows 10 (32-bit and x64-based systems) and ChakraCore prior to the fix [1][2].
Exploitation
An attacker can exploit this vulnerability by hosting a specially crafted website (or injecting content into a compromised site) that, when visited using Microsoft Edge, triggers the memory corruption in the Chakra scripting engine [4]. No authentication or special privileges are required; the attacker only needs to persuade the victim to view the malicious content. The vulnerability can be exploited remotely via a web browser session [2].
Impact
Successful exploitation allows an attacker to execute arbitrary code in the context of the current user within the browser sandbox of Microsoft Edge or ChakraCore [1][2]. If the current user has administrative privileges, the attacker could gain full control of the affected system, including installing programs, viewing/changing/deleting data, and creating new accounts [4]. The attack results in a complete compromise of confidentiality, integrity, and availability (CIA) on the target.
Mitigation
Microsoft released a security update on September 11, 2018, as part of the September 2018 Patch Tuesday, which addresses this vulnerability [4]. The fix is included in cumulative security updates for Microsoft Edge on supported Windows 10 versions. Users should apply the latest Windows updates promptly. For ChakraCore, the fix is available in commit dd5b2e75e7aebe67b5185383080c0648f5353ea0 [3]. No workarounds are listed in the references; enabling Microsoft Defender ATP or other mitigations may reduce risk but do not replace the patch.
- NVD - CVE-2018-8367
- Microsoft ChakraCore Scripting Engine CVE-2018-8367 Remote Memory Corruption Vulnerability
- [CVE-2018-8367] Edge - UAF for Edge on WIP - Qihoo 360 · chakra-core/ChakraCore@dd5b2e7
- Microsoft Edge Multiple Bugs Let Remote Users Execute Arbitrary Code, Obtain Potentially Sensitive Information, Gain Elevated Privileges, and Spoof Content on the Target System
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.11.1 | 1.11.1 |
Affected products
3- Range: ChakraCore
Patches
1dd5b2e75e7ae[CVE-2018-8367] Edge - UAF for Edge on WIP - Qihoo 360
3 files changed · +57 −17
lib/Backend/Lower.cpp+10 −0 modified@@ -3880,6 +3880,16 @@ Lowerer::GenerateArrayAllocHelper(IR::Instr *instr, uint32 * psize, Js::ArrayCal uint32 allocCount = count == 0 ? Js::SparseArraySegmentBase::SMALL_CHUNK_SIZE : count; arrayAllocSize = Js::JavascriptArray::DetermineAllocationSize<ArrayType, 0>(allocCount, nullptr, &alignedHeadSegmentSize); } + + // Note that it is possible for the returned alignedHeadSegmentSize to be greater than INLINE_CHUNK_SIZE because + // of rounding the *entire* object, including the head segment, to the nearest aligned size. In that case, ensure + // that this size is still not larger than INLINE_CHUNK_SIZE size because the head segment is still inlined. This + // keeps consistency with the definition of HasInlineHeadSegment and maintained in the assert below. + uint inlineChunkSize = Js::SparseArraySegmentBase::INLINE_CHUNK_SIZE; + alignedHeadSegmentSize = min(alignedHeadSegmentSize, inlineChunkSize); + + Assert(ArrayType::HasInlineHeadSegment(alignedHeadSegmentSize)); + leaHeadInstr = IR::Instr::New(Js::OpCode::LEA, headOpnd, IR::IndirOpnd::New(dstOpnd, sizeof(ArrayType), TyMachPtr, func), func); isHeadSegmentZeroed = true;
lib/Runtime/Library/JavascriptArray.cpp+46 −16 modified@@ -11814,24 +11814,42 @@ using namespace Js; #endif template <typename T> - void JavascriptArray::InitBoxedInlineSegments(SparseArraySegment<T> * dst, SparseArraySegment<T> * src, bool deepCopy) + void JavascriptArray::InitBoxedInlineSegments(T * instance, bool deepCopy) { // Don't copy the segment map, we will build it again SetFlags(GetFlags() & ~DynamicObjectFlags::HasSegmentMap); - SetHeadAndLastUsedSegment(dst); + SparseArraySegment<typename T::TElement>* src = SparseArraySegment<typename T::TElement>::From(instance->head); + SparseArraySegment<typename T::TElement>* dst; + + if (IsInlineSegment(src, instance)) + { + Assert(src->size <= SparseArraySegmentBase::INLINE_CHUNK_SIZE); + + // Copy head segment data between inlined head segments + dst = DetermineInlineHeadSegmentPointer<T, 0, true>(static_cast<T*>(this)); + dst->left = src->left; + dst->length = src->length; + dst->size = src->size; + } + else + { + // Otherwise, ensure that the new head segment is allocated now in the recycler so that the data can be copied. + // Note: src->next is provided to control whether a leaf segment is allocated just as it is with instance. If + // src->next is non-null, the appropriate update to dst->next will continue below. + dst = SparseArraySegment<typename T::TElement>::AllocateSegment(GetRecycler(), src->left, src->length, src->size, src->next); + } - // Copy head segment data - dst->left = src->left; - dst->length = src->length; - dst->size = src->size; + SetHeadAndLastUsedSegment(dst); dst->CheckLengthvsSize(); + Assert(IsInlineSegment(src, instance) == IsInlineSegment(dst, static_cast<T*>(this))); + CopyArray(dst->elements, dst->size, src->elements, src->size); if (!deepCopy) { - // Without a deep copy, point to the existing next segment + // Without a deep copy, point to the existing next segment from the original instance dst->next = src->next; } else @@ -11845,10 +11863,10 @@ using namespace Js; { // Allocate a new segment in the destination and copy from src // note: PointerValue is to strip SWB wrapping before static_cast - src = static_cast<SparseArraySegment<T>*>(PointerValue(src->next)); + src = static_cast<SparseArraySegment<typename T::TElement>*>(PointerValue(src->next)); dst->next = dst->AllocateSegment(GetRecycler(), src->left, src->length, src->size, src->next); - dst = static_cast<SparseArraySegment<T>*>(PointerValue(dst->next)); + dst = static_cast<SparseArraySegment<typename T::TElement>*>(PointerValue(dst->next)); CopyArray(dst->elements, dst->size, src->elements, src->size); } @@ -11861,14 +11879,20 @@ using namespace Js; } while (dst != nullptr); failFastError.Completed(); } + + // Assert either + // - there is only the head segment + // - the new head segment points to a new next segment + // - the new head segment points to the existing next segment because this is not a deepCopy + Assert(this->head->next == nullptr || this->head->next != src->next || !deepCopy); } JavascriptArray::JavascriptArray(JavascriptArray * instance, bool boxHead, bool deepCopy) : ArrayObject(instance, deepCopy) { if (boxHead) { - InitBoxedInlineSegments(DetermineInlineHeadSegmentPointer<JavascriptArray, 0, true>(this), SparseArraySegment<Var>::From(instance->head), false); + InitBoxedInlineSegments(instance, deepCopy); } else { @@ -11880,13 +11904,19 @@ using namespace Js; } // Allocate a new Array with its own segments and copy the data in instance - // into the new Array + // into the new Array. If the instance being deepCopy'd has an inline head + // segment, then make sure the new instance also has allocation for an inline + // head segment. template <typename T> T * JavascriptArray::DeepCopyInstance(T * instance) { - return RecyclerNewPlusZ(instance->GetRecycler(), - instance->GetTypeHandler()->GetInlineSlotsSize() + sizeof(Js::SparseArraySegmentBase) + instance->head->size * sizeof(typename T::TElement), - T, instance, true /*boxHead*/, true /*deepCopy*/); + size_t allocSize = instance->GetTypeHandler()->GetInlineSlotsSize(); + if (IsInlineSegment(instance->head, instance)) + { + allocSize += sizeof(Js::SparseArraySegmentBase) + instance->head->size * sizeof(typename T::TElement); + } + + return RecyclerNewPlusZ(instance->GetRecycler(), allocSize, T, instance, true /*boxHead*/, true /*deepCopy*/); } ArrayObject* JavascriptArray::DeepCopyInstance(ArrayObject* arrayObject) @@ -12051,7 +12081,7 @@ using namespace Js; { if (boxHead) { - InitBoxedInlineSegments(DetermineInlineHeadSegmentPointer<JavascriptNativeIntArray, 0, true>(this), SparseArraySegment<int>::From(instance->head), deepCopy); + InitBoxedInlineSegments(instance, deepCopy); } else { @@ -12097,7 +12127,7 @@ using namespace Js; { if (boxHead) { - InitBoxedInlineSegments(DetermineInlineHeadSegmentPointer<JavascriptNativeFloatArray, 0, true>(this), SparseArraySegment<double>::From(instance->head), deepCopy); + InitBoxedInlineSegments(instance, deepCopy); } else {
lib/Runtime/Library/JavascriptArray.h+1 −1 modified@@ -904,7 +904,7 @@ namespace Js static JavascriptArray * BoxStackInstance(JavascriptArray * instance, bool deepCopy); static ArrayObject * DeepCopyInstance(ArrayObject * instance); protected: - template <typename T> void InitBoxedInlineSegments(SparseArraySegment<T> * dst, SparseArraySegment<T> * src, bool deepCopy); + template <typename T> void InitBoxedInlineSegments(T * instance, bool deepCopy); template <typename T> static T * BoxStackInstance(T * instance, bool deepCopy); template <typename T> static T * DeepCopyInstance(T * instance);
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-gxcf-6h72-8gxfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-8367ghsaADVISORY
- www.securityfocus.com/bid/105245mitrevdb-entryx_refsource_BID
- www.securitytracker.com/id/1041623mitrevdb-entryx_refsource_SECTRACK
- github.com/chakra-core/ChakraCore/commit/dd5b2e75e7aebe67b5185383080c0648f5353ea0ghsaWEB
- github.com/chakra-core/ChakraCore/pull/5688ghsaWEB
- portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8367ghsax_refsource_CONFIRMWEB
- web.archive.org/web/20210125212221/http://www.securityfocus.com/bid/105245ghsaWEB
- web.archive.org/web/20210517133345/http://www.securitytracker.com/id/1041623ghsaWEB
News mentions
0No linked articles in our index yet.