0x00000139 KERNEL_SECURITY_CHECK_FAILURE

This is not a crash in the usual sense. The kernel validates critical data structures as it uses them, and when a check fails it stops the machine immediately and deliberately - because continuing with corrupted kernel data is how a bug becomes a security compromise. The parameter that matters tells you what kind of corruption was found, and that narrows the field considerably.

Updated 2026-07-27Stop errorAlso written: 0x139, KERNEL SECURITY CHECK FAILURE, kernel_security_check_failure

What you are looking at

:(

Your PC ran into a problem and needs to restart.

Stop code: KERNEL_SECURITY_CHECK_FAILURE

In Event Viewer the matching entries look like this:

Log Name:      System
Source:        BugCheck
Event ID:      1001
Level:         Error

The computer has rebooted from a bugcheck.  The bugcheck was: 0x00000139 (0x0000000000000003, 0xffffb80f2c1a4530, 0xffffb80f2c1a4488, 0x0000000000000000).

What the error actually means

Modern Windows kernels are built with integrity checks compiled in. Stack cookies detect buffer overruns before a function returns. Linked list operations verify that a node's neighbours actually point back at it. Control-flow guards check that an indirect call is going somewhere legitimate.

These checks exist because kernel memory corruption is not merely a stability problem - it is the mechanism behind privilege escalation exploits. So when a check fails, the kernel does not attempt to recover or continue in a degraded state. It halts immediately, on the principle that a stopped machine is safer than a compromised one.

The critical implication for diagnosis: this bugcheck reports detection, not causation. The code that was running when the check failed is frequently the victim - it read a structure someone else had already damaged. The driver named in the dump may be entirely innocent.

Reading the parameters

Parameter 1 identifies which check failed, and it is the most informative value on this page. One thing to watch: Microsoft documents these values in decimal, not hex, which is unusual - almost everything else about bugchecks is hexadecimal. A parameter 1 of 10 means ten, not sixteen. Around thirty values are defined; these are the ones that turn up in practice.

ParameterWhat it holds
0A stack-based buffer was overrun - the legacy /GS violation. Something wrote past the end of a local buffer.
1VTGuard detected an attempt to use an illegal virtual function table. Typically a C++ object was corrupted and a virtual method call then used the corrupted object's pointer.
2Stack cookie instrumentation detected a stack-based buffer overrun - the modern /GS violation. Same class of fault as value 0, caught by newer instrumentation.
3A LIST_ENTRY is corrupted - for example, the same entry removed twice. The most common value by a wide margin, and the one the Cause section below is written for.
5An invalid parameter was passed to a function that treats invalid parameters as fatal.
8A compiler-inserted array bounds check caught an illegal array indexing operation.
10Indirect call guard detected an invalid control transfer - Control Flow Guard catching a call heading somewhere it should not.
11Write guard detected an invalid memory write.
14The reference count for an object is invalid. Usually means an object was released more times than it was referenced.
29An RTL_BALANCED_NODE red-black tree entry is corrupted - the tree equivalent of the LIST_ENTRY case.
2 / 3 / 4Parameter 2 is the address of the trap frame for the exception, parameter 3 the address of the exception record. Both are for debugger use. Parameter 4 is reserved.

What actually triggers it

Because the check catches corruption rather than causing it, the underlying cause list is broad - but the distribution still favours drivers.

CauseHow oftenDetail
Driver bugsCommonOverrunning a buffer, mishandling a linked list, or using an object after freeing it. Storage, network and security drivers are frequent sources because they manipulate lists heavily.
Anti-virus and filter driversCommonSecurity products insert themselves into kernel data structures by design, and a version mismatch after a Windows update produces list corruption reliably.
Failing RAMOccasionalA flipped bit in a list pointer is exactly what the LIST_ENTRY check is looking for. The check fires correctly; the corruption came from hardware.
Unstable memory or CPU settingsOccasionalAn XMP profile beyond what the controller can sustain, or an unstable overclock or undervolt, corrupts data in transit. This produces the same signature as failing memory.
Corrupt system filesRarePossible where a system binary itself is damaged, but not a leading explanation.
MalwareRareWorth mentioning because these checks were designed partly to catch exploitation. A rootkit manipulating kernel structures can trigger them - though a buggy driver is far more likely.

Narrowing it down

Read parameter 1 first, then decide whether you are chasing a driver or chasing memory.

Record parameter 1 across several crashes

Pull the bugcheck records so you have the full parameter set for each:

Get-WinEvent -FilterHashtable @{LogName='System'; Id=1001} |
  Where-Object { $_.Message -match '0x00000139' } |
  Select-Object TimeCreated, Message |
  Format-List
What it tells you

A consistent parameter 1 - especially 0x3 - with a consistent module named in the dump is a specific driver bug. Values that vary between crashes suggest general memory corruption rather than one broken routine.

Check whether the named module is stable across crashes

Open several dumps in WinDbg and compare MODULE_NAME from !analyze -v.

What it tells you

Same module every time points at that driver. A different module each time is the signature of memory corruption, and it is the single most useful thing this bugcheck can tell you - because it decides whether you spend the next week on drivers or on RAM.

Test memory before committing to a driver hunt

Disable XMP or EXPO, then run MemTest86 from USB for at least four passes.

What it tells you

A clean run at stock settings lets you pursue drivers with confidence. Errors end the investigation immediately, and everything above becomes irrelevant.

Fixes, cheapest first

Which branch you take depends on the triage above - a stable module means drivers, a shifting module means memory.

  1. Remove third-party security software

    Effort: 20 minutes · Risk: Low

    Given how often this involves filter drivers, uninstall third-party anti-virus first and run on Windows Defender alone for a few days. Use the vendor's dedicated removal tool rather than the standard uninstaller - these products routinely leave drivers behind.

  2. Update the named driver

    Effort: 20 minutes · Risk: Low

    If dumps consistently name one module, get its current version from the hardware vendor directly. If the crashes started after a driver update, install the previous release instead.

    Remember the caveat: on this bugcheck the named module is frequently a victim rather than the culprit. If updating it changes nothing, do not conclude the driver was fine - conclude that the corruption is coming from elsewhere.

  3. Return memory and CPU to stock

    Effort: 10 minutes · Risk: Low

    Disable XMP, EXPO, any manual memory tuning, and any CPU overclock or undervolt. Curve optimiser settings on Ryzen and undervolts on Intel are common causes of corruption that looks exactly like a driver bug.

    Run at stock for several days before drawing conclusions.

  4. Test memory thoroughly

    Effort: Overnight · Risk: None

    MemTest86 from USB, minimum four passes, at stock settings. If errors appear, test each module individually in the same slot to identify which one.

  5. Verify system files

    Effort: 30 minutes · Risk: None

    Cheap to rule out.

    1. sfc /scannow
    2. DISM /Online /Cleanup-Image /RestoreHealth
    3. sfc /scannow again
  6. Run Driver Verifier

    Effort: Several hours · Risk: Medium

    Verifier is well suited to this bugcheck because Special Pool catches buffer overruns at the moment they happen, rather than when a later check notices the damage. That converts an unhelpful dump naming a random module into one naming the actual offender.

    1. Create a restore point and confirm you can reach Safe Mode.
    2. Run verifier, choose custom settings, enable Special Pool, Pool Tracking and Force IRQL checking.
    3. Select non-Microsoft drivers only.
    4. Use the machine until it bugchecks, then read the dump.
    5. Run verifier /reset and reboot.
    Watch out

    Verifier deliberately increases crashes and can cause a boot loop. Run verifier /bootmode resetonbootfail before enabling any checks - it makes Verifier disable itself automatically if the machine fails to start, which removes most of the risk. Your manual exit is Safe Mode followed by verifier /reset. Full settings and the escape route are in the Driver Verifier guide.

When it is the hardware, not Windows

Signals that memory or CPU hardware is corrupting data rather than a driver mishandling it:

The overclock item deserves more weight than people give it. An undervolt that passes hours of benchmarking can still be unstable at the light, bursty loads of ordinary desktop use, and the corruption it produces surfaces precisely as a failed integrity check. If the machine is tuned at all, returning it to stock is not a formality - it is the test.

Frequently asked

Does this mean I have a virus?

Almost certainly not, despite the name. The word 'security' here refers to the kernel's internal integrity checks - mechanisms built to make memory corruption fail safely rather than become exploitable. They fire far more often for buggy drivers and bad RAM than for anything malicious. A scan is reasonable diligence, but do not let the name redirect the investigation.

The dump names a driver. Is that definitely the faulty one?

Less reliably than on most bugchecks. The check fires when corrupted data is used, which can be a long way from where it was damaged. If updating the named driver changes nothing, that is informative rather than disappointing - it means you are looking at the victim. Driver Verifier's Special Pool exists to close that gap by faulting at the moment of the overrun.

What does parameter 1 = 3 mean in practice?

LIST_ENTRY corruption. Windows keeps many things in doubly-linked lists, where each node points forward and backward. When an entry is added or removed the kernel verifies the neighbours agree, and value 3 means they did not.

Microsoft lists the specific driver mistakes that produce it: removing the same entry twice without reinserting it between the two removals; freeing a structure that contains a LIST_ENTRY without first taking it off its list; using a list concurrently from several threads without proper synchronisation; and corrupting a kernel synchronisation object such as a KEVENT or a periodic KTIMER, which are themselves held in lists.

The important caveat is timing: the inconsistency is detected when the list is next walked, which can be long after the damage was done. That is why the named module is so often innocent, and why Driver Verifier with Special Pool is the tool that actually finds these - it faults at the moment of the overrun rather than when someone later notices.

Why does Windows crash instead of just recovering?

Because it cannot know how far the damage extends. Corrupted kernel structures are the foundation of privilege escalation attacks, and continuing risks writing user data into unpredictable places or executing attacker-controlled code. Stopping is the deliberate, safer choice - the bugcheck is the mitigation working, not failing.