CVE-2018-0946
Description
A remote code execution vulnerability exists in Microsoft Edge's and ChakraCore's scripting engine due to improper memory object handling, allowing attackers to execute arbitrary code via a crafted web page.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A remote code execution vulnerability exists in Microsoft Edge's and ChakraCore's scripting engine due to improper memory object handling, allowing attackers to execute arbitrary code via a crafted web page.
Vulnerability
CVE-2018-0946 is a memory corruption vulnerability in the scripting engine (Chakra) used by Microsoft Edge and the open-source ChakraCore library [1][2]. The bug is triggered when the scripting engine improperly handles objects in memory while processing specially crafted JavaScript content [3]. The vulnerability affects all supported versions of Microsoft Edge on Windows 10, as well as ChakraCore prior to security updates released in May 2018 [2].
Exploitation
An attacker must host a malicious web page or inject script into a trusted site that the victim then accesses through Microsoft Edge [3]. No additional authentication or user interaction beyond opening the crafted page is required, as the scripting engine automatically parses the JavaScript, triggering the memory corruption condition [1]. The vulnerability was credited to Lokihardt of Google Project Zero, indicating a capable researcher with detailed understanding of the flaw [2].
Impact
Successful exploitation grants the attacker arbitrary code execution within the context of the current user in the Edge sandbox [3]. The attacker could then install programs, view, change, or delete data, or create new accounts with the user's full rights [1]. This represents a complete compromise of client confidentiality, integrity, and availability.
Mitigation
Microsoft released security updates in May 2018 as part of Patch Tuesday (May 8, 2018) that address this vulnerability [3]. Affected versions of Microsoft Edge are updated via Windows Update; ChakraCore users should update to the latest patched version. No workarounds are documented in the available references. ChakraCore 1.11 entered end-of-life with security update support ending March 9, 2021 [4].
- NVD - CVE-2018-0946
- Microsoft Edge Scripting Engine CVE-2018-0946 Remote Memory Corruption Vulnerability
- Microsoft Edge Multiple Bugs Let Remote Users Execute Arbitrary Code, Obtain Potentially Sensitive Information, and Bypass Security Restrictions on the Target System
- GitHub - chakra-core/ChakraCore: ChakraCore is an open source Javascript engine with a C API.
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.4 | 1.8.4 |
Affected products
3- Range: ChakraCore
Patches
1bee1e247bf6a[CVE-2018-8130] [CVE-2018-0946] move allocators to ServerScriptContext, add missing marshalling code
13 files changed · +52 −39
lib/Backend/NativeCodeGenerator.cpp+1 −2 modified@@ -3257,8 +3257,7 @@ NativeCodeGenerator::FreeNativeCodeGenAllocation(void* codeAddress) #if PDATA_ENABLED && defined(_WIN32) DelayDeletingFunctionTable::Clear(); #endif - ThreadContext * context = this->scriptContext->GetThreadContext(); - HRESULT hr = JITManager::GetJITManager()->FreeAllocation(context->GetRemoteThreadContextAddr(), (intptr_t)codeAddress); + HRESULT hr = JITManager::GetJITManager()->FreeAllocation(this->scriptContext->GetRemoteScriptAddr(), (intptr_t)codeAddress); JITManager::HandleServerCallResult(hr, RemoteCallType::MemFree); } else if(this->backgroundAllocators)
lib/Backend/ServerScriptContext.cpp+15 −1 modified@@ -26,13 +26,19 @@ ServerScriptContext::ServerScriptContext(ScriptContextDataIDL * contextData, Ser m_asmJsInterpreterThunkBufferManager(&m_sourceCodeArena, threadContextInfo->GetThunkPageAllocators(), nullptr, threadContextInfo, _u("Asm.js interpreter thunk buffer"), GetThreadContext()->GetProcessHandle()), m_domFastPathHelperMap(nullptr), m_moduleRecords(&HeapAllocator::Instance), + m_codeGenAlloc(nullptr, nullptr, threadContextInfo, threadContextInfo->GetCodePageAllocators(), threadContextInfo->GetProcessHandle()), m_globalThisAddr(0), #ifdef PROFILE_EXEC m_codeGenProfiler(nullptr), #endif m_refCount(0), m_isClosed(false) { + +#if !TARGET_64 && _CONTROL_FLOW_GUARD + m_codeGenAlloc.canCreatePreReservedSegment = threadContextInfo->CanCreatePreReservedSegment(); +#endif + #ifdef PROFILE_EXEC if (Js::Configuration::Global.flags.IsEnabled(Js::ProfileFlag)) { @@ -357,7 +363,9 @@ ServerScriptContext::Close() { Assert(!IsClosed()); m_isClosed = true; - + + m_codeGenAlloc.emitBufferManager.Decommit(); + #ifdef STACK_BACK_TRACE ServerContextManager::RecordCloseContext(this); #endif @@ -381,6 +389,12 @@ ServerScriptContext::Release() } } +OOPCodeGenAllocators * +ServerScriptContext::GetCodeGenAllocators() +{ + return &m_codeGenAlloc; +} + Field(Js::Var)* ServerScriptContext::GetModuleExportSlotArrayAddress(uint moduleIndex, uint slotIndex) {
lib/Backend/ServerScriptContext.h+3 −0 modified@@ -87,6 +87,7 @@ class ServerScriptContext : public ScriptContextInfo Js::ScriptContextProfiler * GetCodeGenProfiler() const; ServerThreadContext* GetThreadContext() { return threadContextHolder.threadContextInfo; } + OOPCodeGenAllocators * GetCodeGenAllocators(); ArenaAllocator * GetSourceCodeArena(); void Close(); void AddRef(); @@ -107,6 +108,8 @@ class ServerScriptContext : public ScriptContextInfo uint m_refCount; + OOPCodeGenAllocators m_codeGenAlloc; + bool m_isPRNGSeeded; bool m_isClosed; #endif
lib/Backend/ServerThreadContext.cpp+12 −15 modified@@ -14,24 +14,21 @@ ServerThreadContext::ServerThreadContext(ThreadContextDataIDL* data, ProcessCont m_numericPropertyBV(nullptr), m_preReservedSectionAllocator(processContext->processHandle), m_sectionAllocator(processContext->processHandle), - m_thunkPageAllocators(nullptr, /* allocXData */ false, &m_sectionAllocator, nullptr, processContext->processHandle), m_codePageAllocators(nullptr, ALLOC_XDATA, &m_sectionAllocator, &m_preReservedSectionAllocator, processContext->processHandle), + m_thunkPageAllocators(nullptr, /* allocXData */ false, &m_sectionAllocator, nullptr, processContext->processHandle), #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM) m_jitThunkEmitter(this, &m_sectionAllocator, processContext->processHandle), #endif - m_codeGenAlloc(nullptr, nullptr, this, &m_codePageAllocators, processContext->processHandle), m_pageAlloc(nullptr, Js::Configuration::Global.flags, PageAllocatorType_BGJIT, AutoSystemInfo::Data.IsLowMemoryProcess() ? PageAllocator::DefaultLowMaxFreePageCount : PageAllocator::DefaultMaxFreePageCount ), - processContext(processContext) + processContext(processContext), + m_canCreatePreReservedSegment(data->allowPrereserveAlloc != FALSE) { m_pid = GetProcessId(processContext->processHandle); -#if !TARGET_64 && _CONTROL_FLOW_GUARD - m_codeGenAlloc.canCreatePreReservedSegment = data->allowPrereserveAlloc != FALSE; -#endif m_numericPropertyBV = HeapNew(BVSparse<HeapAllocator>, &HeapAllocator::Instance); } @@ -121,22 +118,16 @@ ServerThreadContext::GetThunkPageAllocators() return &m_thunkPageAllocators; } -CustomHeap::OOPCodePageAllocators * -ServerThreadContext::GetCodePageAllocators() -{ - return &m_codePageAllocators; -} - SectionAllocWrapper * ServerThreadContext::GetSectionAllocator() { return &m_sectionAllocator; } -OOPCodeGenAllocators * -ServerThreadContext::GetCodeGenAllocators() +CustomHeap::OOPCodePageAllocators * +ServerThreadContext::GetCodePageAllocators() { - return &m_codeGenAlloc; + return &m_codePageAllocators; } #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM) @@ -172,6 +163,12 @@ ServerThreadContext::GetForegroundPageAllocator() return &m_pageAlloc; } +bool +ServerThreadContext::CanCreatePreReservedSegment() const +{ + return m_canCreatePreReservedSegment; +} + bool ServerThreadContext::IsNumericProperty(Js::PropertyId propertyId) {
lib/Backend/ServerThreadContext.h+2 −2 modified@@ -55,7 +55,6 @@ class ServerThreadContext : public ThreadContextInfo virtual ptrdiff_t GetChakraBaseAddressDifference() const override; virtual ptrdiff_t GetCRTBaseAddressDifference() const override; - OOPCodeGenAllocators * GetCodeGenAllocators(); #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM) OOPJITThunkEmitter * GetJITThunkEmitter(); #endif @@ -72,6 +71,7 @@ class ServerThreadContext : public ThreadContextInfo intptr_t GetRuntimeChakraBaseAddress() const; intptr_t GetRuntimeCRTBaseAddress() const; + bool CanCreatePreReservedSegment() const; static intptr_t GetJITCRTBaseAddress(); @@ -84,7 +84,6 @@ class ServerThreadContext : public ThreadContextInfo SectionAllocWrapper m_sectionAllocator; CustomHeap::OOPCodePageAllocators m_thunkPageAllocators; CustomHeap::OOPCodePageAllocators m_codePageAllocators; - OOPCodeGenAllocators m_codeGenAlloc; #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM) OOPJITThunkEmitter m_jitThunkEmitter; #endif @@ -96,5 +95,6 @@ class ServerThreadContext : public ThreadContextInfo CriticalSection m_cs; uint m_refCount; + bool m_canCreatePreReservedSegment; }; #endif
lib/JITClient/JITManager.cpp+2 −2 modified@@ -586,15 +586,15 @@ JITManager::CloseScriptContext( HRESULT JITManager::FreeAllocation( - __in PTHREADCONTEXT_HANDLE threadContextInfoAddress, + __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress, __in intptr_t codeAddress) { Assert(IsOOPJITEnabled()); HRESULT hr = E_FAIL; RpcTryExcept { - hr = ClientFreeAllocation(m_rpcBindingHandle, threadContextInfoAddress, codeAddress); + hr = ClientFreeAllocation(m_rpcBindingHandle, scriptContextInfoAddress, codeAddress); } RpcExcept(RpcExceptionFilter(RpcExceptionCode())) {
lib/JITClient/JITManager.h+2 −2 modified@@ -79,7 +79,7 @@ class JITManager __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress); HRESULT FreeAllocation( - __in PTHREADCONTEXT_HANDLE threadContextInfoAddress, + __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress, __in intptr_t codeAddress); HRESULT SetIsPRNGSeeded( @@ -213,7 +213,7 @@ class JITManager { Assert(false); return E_FAIL; } HRESULT FreeAllocation( - __in PTHREADCONTEXT_HANDLE threadContextInfoAddress, + __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress, __in intptr_t codeAddress) { Assert(false); return E_FAIL; }
lib/JITIDL/ChakraJIT.idl+1 −1 modified@@ -85,7 +85,7 @@ interface IChakraJIT HRESULT FreeAllocation( [in] handle_t binding, - [in] PTHREADCONTEXT_HANDLE threadContextInfoAddress, + [in] PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress, [in] CHAKRA_PTR codeAddress); HRESULT NewInterpreterThunkBlock(
lib/JITServer/JITServer.cpp+4 −4 modified@@ -676,10 +676,10 @@ ServerIsInterpreterThunkAddr( HRESULT ServerFreeAllocation( /* [in] */ handle_t binding, - /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo, + /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfo, /* [in] */ intptr_t codeAddress) { - ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo); + ServerScriptContext* context = (ServerScriptContext*)DecodePointer(scriptContextInfo); if (context == nullptr) { @@ -709,7 +709,7 @@ ServerIsNativeAddr( *result = false; - ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo); + ServerThreadContext* context = (ServerThreadContext*)DecodePointer(threadContextInfo); if (context == nullptr) { Assert(false); @@ -850,7 +850,7 @@ ServerRemoteCodeGen( nullptr, nullptr, jitWorkItem->GetPolymorphicInlineCacheInfo(), - threadContextInfo->GetCodeGenAllocators(), + scriptContextInfo->GetCodeGenAllocators(), #if !FLOATVAR nullptr, // number allocator #endif
lib/Runtime/Base/ScriptContext.cpp+7 −6 modified@@ -701,6 +701,13 @@ namespace Js } #endif +#if ENABLE_NATIVE_CODEGEN + if (m_remoteScriptContextAddr) + { + JITManager::GetJITManager()->CloseScriptContext(m_remoteScriptContextAddr); + } +#endif + #ifdef ENABLE_SCRIPT_PROFILING // Stop profiling if present DeRegisterProfileProbe(S_OK, nullptr); @@ -1452,12 +1459,6 @@ namespace Js #endif } -#if ENABLE_NATIVE_CODEGEN - if (m_remoteScriptContextAddr) - { - JITManager::GetJITManager()->CloseScriptContext(m_remoteScriptContextAddr); - } -#endif this->PrintStats(); } }
lib/Runtime/Library/DataView.cpp+1 −2 modified@@ -597,8 +597,7 @@ namespace Js { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject); } - - return arrayBuffer; + return CrossSite::MarshalVar(scriptContext, arrayBuffer); } Var DataView::EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...)
lib/Runtime/Library/WebAssemblyInstance.cpp+1 −1 modified@@ -121,7 +121,7 @@ WebAssemblyInstance::GetterExports(RecyclableObject* function, CallInfo callInfo Assert(UNREACHED); exports = scriptContext->GetLibrary()->GetUndefined(); } - return exports; + return CrossSite::MarshalVar(scriptContext, exports); } WebAssemblyInstance *
lib/Runtime/Library/WebAssemblyMemory.cpp+1 −1 modified@@ -239,7 +239,7 @@ WebAssemblyMemory::EntryGetterBuffer(RecyclableObject* function, CallInfo callIn WebAssemblyMemory* memory = WebAssemblyMemory::FromVar(args[0]); Assert(ArrayBuffer::Is(memory->m_buffer)); - return memory->m_buffer; + return CrossSite::MarshalVar(scriptContext, memory->m_buffer); } WebAssemblyMemory *
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
10- www.exploit-db.com/exploits/44758/mitreexploitx_refsource_EXPLOIT-DB
- github.com/advisories/GHSA-wc67-4cg3-35wfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-0946ghsaADVISORY
- www.securityfocus.com/bid/103989mitrevdb-entryx_refsource_BID
- www.securitytracker.com/id/1040844mitrevdb-entryx_refsource_SECTRACK
- github.com/chakra-core/ChakraCore/commit/bee1e247bf6acbc8c862c7fc1d597ce9cab7446eghsaWEB
- portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-0946ghsax_refsource_CONFIRMWEB
- web.archive.org/web/20210125210449/https://www.securityfocus.com/bid/103989ghsaWEB
- web.archive.org/web/20211204185256/http://www.securitytracker.com/id/1040844ghsaWEB
- www.exploit-db.com/exploits/44758ghsaWEB
News mentions
0No linked articles in our index yet.