VYPR
High severityNVD Advisory· Published Apr 9, 2019· Updated Aug 4, 2024

CVE-2019-0806

CVE-2019-0806

Description

A remote code execution vulnerability in Microsoft Edge's Chakra scripting engine due to memory corruption, potentially allowing an attacker to gain the same user rights as the current user.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A remote code execution vulnerability in Microsoft Edge's Chakra scripting engine due to memory corruption, potentially allowing an attacker to gain the same user rights as the current user.

Vulnerability

Analysis

CVE-2019-0806 is a remote code execution vulnerability in the Chakra scripting engine used by Microsoft Edge, caused by improper handling of objects in memory. The official description categorizes it as a 'Chakra Scripting Engine Memory Corruption Vulnerability' [1]. The root cause is a type confusion issue in the JIT compiler, where the engine fails to properly invalidate prototype caches when storing fields, allowing an attacker to corrupt memory [3].

Exploitation

To exploit this vulnerability, an attacker would need to host a specially crafted website (or leverage a compromised site that accepts user content) and persuade a user to visit it in Microsoft Edge. No authentication is required, as the attack vector is through a web browser. The vulnerability can be triggered without any user interaction beyond visiting the malicious page [1].

Impact

Successful exploitation could allow an attacker to execute arbitrary code in the context of the current user. If the user has administrative privileges, the attacker could install programs; view, change, or delete data; or create new accounts with full user rights. The vulnerability has a CVSS score indicating high severity [1].

Mitigation

Microsoft released a security update for this vulnerability on April 9, 2019, as part of their monthly Patch Tuesday. Users should ensure Microsoft Edge and Windows are fully updated. The fix addresses the memory corruption by adding checks to invalidate prototype caches when appropriate [3]. ChakraCore, the open-source engine, received a patch in commit 50d1e46aac450f236927b309854e77fce4acd49f [2].

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.

PackageAffected versionsPatched versions
Microsoft.ChakraCoreNuGet
< 1.11.81.11.8

Affected products

3

Patches

1
50d1e46aac45

CVE-2019-0806 Edge - Chakra JIT Type Confusion with

https://github.com/chakra-core/ChakraCorePaul LeathersMar 21, 2019via ghsa
7 files changed · +42 6
  • lib/Backend/GlobOptFields.cpp+3 1 modified
    @@ -494,7 +494,9 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
         case Js::OpCode::NewScObjectNoCtor:
             if (inGlobOpt)
             {
    -            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
    +            // Opcodes that make an object into a prototype may break object-header-inlining and final type opt.
    +            // Kill all known object layouts.
    +            KillAllObjectTypes(bv);
             }
             break;
     
    
  • lib/Backend/JITType.cpp+1 1 modified
    @@ -35,7 +35,7 @@ JITType::BuildFromJsType(__in Js::Type * jsType, __out JITType * jitType)
     
             Js::DynamicTypeHandler * handler = dynamicType->GetTypeHandler();
             data->handler.isObjectHeaderInlinedTypeHandler = handler->IsObjectHeaderInlinedTypeHandler();
    -        data->handler.isLocked = handler->GetIsLocked();
    +        data->handler.flags = handler->GetFlags();
             data->handler.inlineSlotCapacity = handler->GetInlineSlotCapacity();
             data->handler.offsetOfInlineSlots = handler->GetOffsetOfInlineSlots();
             data->handler.slotCapacity = handler->GetSlotCapacity();
    
  • lib/Backend/JITTypeHandler.cpp+7 1 modified
    @@ -19,7 +19,13 @@ JITTypeHandler::IsObjectHeaderInlinedTypeHandler() const
     bool
     JITTypeHandler::IsLocked() const
     {
    -    return m_data.isLocked != FALSE;
    +    return Js::DynamicTypeHandler::GetIsLocked(m_data.flags);
    +}
    +
    +bool
    +JITTypeHandler::IsPrototype() const
    +{
    +    return Js::DynamicTypeHandler::GetIsPrototype(m_data.flags);
     }
     
     uint16
    
  • lib/Backend/JITTypeHandler.h+1 0 modified
    @@ -12,6 +12,7 @@ class JITTypeHandler
     
         bool IsObjectHeaderInlinedTypeHandler() const;
         bool IsLocked() const;
    +    bool IsPrototype() const;
     
         uint16 GetInlineSlotCapacity() const;
         uint16 GetOffsetOfInlineSlots() const;
    
  • lib/Backend/Lower.cpp+23 0 modified
    @@ -7353,6 +7353,19 @@ Lowerer::GenerateStFldWithCachedType(IR::Instr *instrStFld, bool* continueAsHelp
         {
             Assert(labelTypeCheckFailed == nullptr && labelBothTypeChecksFailed == nullptr);
             AssertMsg(!instrStFld->HasBailOutInfo(), "Why does a direct field store have bailout?");
    +
    +        if (propertySymOpnd->HasInitialType() && propertySymOpnd->HasFinalType())
    +        {
    +            bool isPrototypeTypeHandler = propertySymOpnd->GetInitialType()->GetTypeHandler()->IsPrototype();
    +            if (isPrototypeTypeHandler)
    +            {
    +                LoadScriptContext(instrStFld);
    +                m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
    +                IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
    +                instrStFld->InsertBefore(invalidateCallInstr);
    +                m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
    +            }
    +        }
             instrStFld->Remove();
             return true;
         }
    @@ -8177,6 +8190,16 @@ Lowerer::GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySy
     
         // Now do the store.
         GenerateDirectFieldStore(instrStFld, propertySymOpnd);
    +
    +    bool isPrototypeTypeHandler = initialType->GetTypeHandler()->IsPrototype();
    +    if (isPrototypeTypeHandler)
    +    {
    +        LoadScriptContext(instrStFld);
    +        m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
    +        IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
    +        instrStFld->InsertBefore(invalidateCallInstr);
    +        m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
    +    }
     }
     
     bool
    
  • lib/JITIDL/JITTypes.h+1 1 modified
    @@ -90,7 +90,7 @@ typedef IDL_DEF([ref]) PSCRIPTCONTEXT_HANDLE * PPSCRIPTCONTEXT_HANDLE;
     typedef struct TypeHandlerIDL
     {
         IDL_Field(boolean) isObjectHeaderInlinedTypeHandler;
    -    IDL_Field(boolean) isLocked;
    +    IDL_Field(unsigned char) flags;
     
         IDL_Field(unsigned short) inlineSlotCapacity;
         IDL_Field(unsigned short) offsetOfInlineSlots;
    
  • lib/Runtime/Types/TypeHandler.h+6 2 modified
    @@ -348,13 +348,17 @@ namespace Js
                  (v) Seal
                 (vi) Freeze
             */
    -        bool GetIsLocked() const { return (this->flags & IsLockedFlag) != 0; }
    +        bool GetIsLocked() const { return GetIsLocked(this->flags); }
    +        static bool GetIsLocked(byte flags) { return (flags & IsLockedFlag) != 0; }
     
             bool GetIsShared() const { return (this->flags & IsSharedFlag) != 0; }
             bool GetMayBecomeShared() const { return (this->flags & MayBecomeSharedFlag) != 0; }
             bool GetIsOrMayBecomeShared() const { return (this->flags & (MayBecomeSharedFlag | IsSharedFlag)) != 0; }
             bool GetHasKnownSlot0() const { return (this->flags & HasKnownSlot0Flag) != 0; }
    -        bool GetIsPrototype() const { return (this->flags & IsPrototypeFlag) != 0; }
    +
    +        bool GetIsPrototype() const { return GetIsPrototype(this->flags); }
    +        static bool GetIsPrototype(byte flags) { return (flags & IsPrototypeFlag) != 0; }
    +
             bool GetIsInlineSlotCapacityLocked() const { return (this->propertyTypes & PropertyTypesInlineSlotCapacityLocked) != 0; }
     
             void LockTypeHandler() { Assert(IsLockable()); SetFlags(IsLockedFlag); }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.