Summary
A Windows Server 2025 container host bugchecks repeatedly with a NULL-pointer dereference in ksecdd!KSecReferenceListEntry+0x1e while serving HTTPS traffic from IIS running inside Windows Server containers.
The fault is reached from two distinct HTTP.sys paths: the TLS send/disconnect path and the asynchronous connection free path. In both cases rax is 0x0000000000000000 and the faulting instruction is cmp dword ptr [rax],0.
The defect is scale-dependent: it reproduces reliably with approximately 30 concurrent containers and does not reproduce with a small number of containers. This points to per-silo security-context state in ksecdd/ksecpkg that is not initialized or not safely published as the number of silos grows.
The host is fully patched. Standard mitigations (disabling HTTP/2 over TLS, disabling TLS 1.3, staggering container starts, HTTP warm-up before HTTPS, eliminating client-side connection churn) have no effect. Driver Verifier with Special Pool enabled on ksecdd.sys produced no pool violation, indicating a genuine NULL pointer rather than a use-after-free.
Environment
| Item | Value |
|---|---|
| Host OS | Windows Server 2025, build 10.0.26100.33296 |
| Host type | Physical |
| Container runtime | Docker 29.6.2 |
| Container isolation | Process isolation |
| Container base image | dotnet/framework/aspnet:4.8.1-windowsservercore-ltsc2025 |
| Concurrent containers | 30 |
| Workload in container | IIS + ASP.NET application (Acumatica ERP), .NET Framework 4.8 |
| TLS | HTTPS on port 443, HTTP.sys, self-signed certificate |
| Client | Selenium browser automation + .NET Framework 4.8 HttpClient health probes |
Problem Description
The host bugchecks during automated test runs. Crashes occur early in the container lifetime, shortly after containers start and begin serving HTTPS traffic. No container teardown is in progress at the time of the crash.
Each test run starts approximately 30 Windows Server containers. Each container runs IIS with a single HTTPS binding using a self-signed certificate installed from a fixed PFX at first container start. The binding is created once and is not modified thereafter.
Because the crash is a host bugcheck, all 30 containers and the build agent are lost, failing the entire pipeline run.
Bugcheck Details
Bugcheck: SYSTEM_SERVICE_EXCEPTION (0x0000003B)
Exception: 0xC0000005 — access violation
Read address: 0000000000000000
Faulting instruction:
ksecdd!KSecReferenceListEntry+1e
fffff803`59f34d4e 833800 cmp dword ptr [rax],0
rax is NULL in all observed occurrences.
Stack 1 — TLS send / egress disconnect path (w3wp.exe)
ksecdd!KSecReferenceListEntry+0x1e
ksecpkg!SslSealMessage+0x58
ksecdd!EncryptMessage+0x9f
HTTP!UxpSslSealMessage+0xdb
HTTP!UxpSslCommonSendData+0x31d
HTTP!UxSslSendDisconnect+0xde
HTTP!UxSslInitiateEgressDisconnect+0x140
HTTP!UxpTpDirectTransmitFromMdl+0x3c1
HTTP!UxpTpDirectTransmit+0x97
HTTP!UxpTpFastTransmit+0x294
HTTP!UxTpTransmitPacket+0x226
HTTP!UlSendData+0x146
HTTP!UlFastSendHttpResponseOld+0x18b9
HTTP!UlSendResponseOrEntityBodyFastIoOld+0xf8e
HTTP!UlpSendResponseOrEntityBodyFastIo+0x173
HTTP!UxFastIoDeviceControl+0xc6
nt!IopXxxControlFile+0x23a9dd
nt!NtDeviceIoControlFile+0x5e
nt!KiSystemServiceCopyEnd+0x25
Stack 2 — asynchronous connection free path (System, HTTP.sys thread pool worker)
ksecdd!KSecReferenceListEntry+0x1e
ksecpkg!SslReferenceContext+0x35
ksecpkg!SslDeleteKernelContext+0x24
ksecdd!DeleteSecurityContextInternal+0xfc
ksecdd!SspiDeleteSecurityContextAsync+0x1a
HTTP!UxSslFreeConnection+0xad
HTTP!UlpThreadPoolWorker+0x13c
nt!PspSystemThreadStartup+0x5a
nt!KiStartSystemThread+0x34
Both stacks terminate at the same NULL dereference in the per-context list walk, reached from independent code paths and from different process contexts.
Reproduction
Reproduces:
- Approximately 30 concurrent Windows Server containers, each running IIS with an HTTPS binding, under automated browser and HTTP client load.
- Crash occurs early in the run, typically shortly after containers begin serving traffic.
Does not reproduce:
- With a small number (5) of concurrent containers under the same workload.
This scale-dependence is the clearest signal available and suggests the defect is a function of silo count rather than of request volume, request pattern, or connection lifetime.
Driver Verifier Results
Driver Verifier was enabled on the host:
verifier /standard /driver ksecdd.sys ksecpkg.sys HTTP.sys
Observations at the time of the bugcheck:
- All
ksecdd.sys pool allocations were routed through Special Pool (Pool Allocations Succeeded SpecialPool 0x545d, Pool Allocations Failed 0x0).
- No pool violation was raised. The bugcheck remained the original
0xC0000005 NULL read at ksecdd!KSecReferenceListEntry+0x1e, not 0xC1, 0xD5, or 0xD6.
Interpretation: with Special Pool active, an access to freed pool would be expected to trap at the point of access with allocation and free stacks recorded. That did not occur. Combined with READ_ADDRESS: 0, this indicates the context list pointer is genuinely NULL — never created, or not yet published — rather than freed and reused.
Verifier state also showed large numbers of live per-silo allocations from:
ksecdd!KsecdCreateSiloNotification+0x1a6
ksecdd!KsecPerfCountersInitSilo+0x4b
ksecdd!InitializePackages+0xeb / +0x114
alongside a much smaller number of ksecdd!KSecCreateContextList+0x1d (tag SeCL) allocations — the structure that KSecReferenceListEntry walks.
Mitigations Tested — All Ineffective
| Mitigation | Result |
|---|---|
| Latest cumulative update on host | Already applied; crash persists |
| EnableHttp2Tls = 0 (container hive) | No effect |
| TLS 1.3 disabled via SCHANNEL registry (container hive), TLS 1.2 forced | No effect |
| Staggered container starts (several seconds apart) | No effect |
| HTTP warm-up request before any HTTPS traffic | No effect |
| Client-side connection churn eliminated (shared HttpClient, keep-alive, no Connection: close, response bodies fully drained) | Reduced crash frequency; did not eliminate |
| Certificate binding verified stable — one-time binding from fixed PFX, no rebinding on restart | Not a factor |
| Reducing concurrent container count | Crash does not reproduce — only effective mitigation found |
Analysis
The evidence is consistent with a missing NULL check or an initialization/publication ordering issue on per-silo security-context state in ksecdd/ksecpkg, exposed when many silos initialize and serve TLS traffic concurrently:
- The faulting pointer is NULL, not freed (Verifier Special Pool clean).
- Two independent code paths — TLS send and asynchronous connection free — reach the same NULL dereference.
- The defect is a function of silo count, not request volume: reducing containers eliminates it while the same workload per container is retained.
- No configuration change affecting protocol version, protocol features, certificate handling, or client connection behavior has any effect.
- Using ltsc2022 image instead of ltsc2025 works and does not lead to bugcheck.
A user-mode workload should not be able to bugcheck the host under any circumstances, including high connection concurrency across containers.
Impact
- Complete host bugcheck, losing all 30 containers and the build agent.
- Automated test pipeline fails.
- Occurs always.
- Current workaround — none.
Request
- Confirm whether this matches a known defect in
ksecdd.sys / ksecpkg.sys / HTTP.sys on Windows Server 2025, and whether a fix or private hotfix is available.
- If not known, please advise on additional data collection. Kernel dumps from both stacks are available, as are Driver Verifier–enabled dumps.
- Advise on any supported configuration that avoids the code path while retaining HTTPS in containers at this concurrency.
Attachments (can send by request)
-
MEMORY.DMP — Stack 1 (UxpSslSealMessage send path)
-
MEMORY.DMP — Stack 2 (UxSslFreeConnection async free path)
-
MEMORY.DMP — with Driver Verifier enabled on ksecdd.sys, ksecpkg.sys, HTTP.sys