7-Zip CVE-2026-48095: NTFS Heap Overflow Enables Vtable Hijacking

A critical heap buffer overflow in 7-Zip 26.00 allows for Remote Code Execution (RCE) via specially crafted NTFS files, regardless of file extension. While ver…

7-Zip CVE-2026-48095: NTFS Heap Overflow Enables Vtable Hijacking

On May 22, 2026, GitHub Security Lab published advisory GHSL-2026-140, detailing a critical vulnerability in 7-Zip's NTFS handler. Researcher Jaroslav Lobačevski demonstrated how a 32-bit shift error in C++ leads to a single-byte heap under-allocation, clearing a path for vtable hijacking and arbitrary code execution. The vulnerability affects version 26.00 and all prior versions supporting compressed NTFS streams. A fix has been available since version 26.01, released April 27, 2026. Because public disclosure occurred nearly a month after the patch, users who do not rely on automated updates have faced a significant window of exposure.

Key Takeaways
  • An undefined behavior shift (UInt32)1 << 32 in CInStream::GetCuSize() allocates just 1 byte instead of the intended 256 MB for the NTFS compressed input buffer, resulting in a controlled heap overflow.
  • The NTFS handler is triggered by the NTFS signature at offset 3, regardless of the file extension (.zip, .7z, .rar, or none), rendering extension-based filtering ineffective.
  • The CInStream stream object (304 bytes), allocated adjacent to _inBuf, has its vtable pointer overwritten during the first read iteration; the second iteration then dispatches through the corrupted vtable.
  • CVSS 3.1: 8.8 (High) with vector AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. A Python-based PoC generates sparse images that appear to be 512 MB but occupy only 8 KB of physical space.

The Bug: When 1 << 32 Equals 1, Not 4 Billion

The flaw is located in NtfsHandler.cpp:687 within the CInStream::GetCuSize() function. The code calculates buffer size using (UInt32)1 << (BlockSizeLog + CompressionUnit). When the NTFS parser accepts a boot sector with ClusterSizeLog >= 28 and a compressed attribute where CompressionUnit == 4, the exponent reaches 32. In C++, (UInt32)1 << 32 is undefined behavior. On x86 architectures, the processor masks the shift to 5 bits, resulting in 1 << 0 = 1. On x64, the same result impacts _inBuf, even if _outBuf attempts an 8 GB allocation.

The UBSan report included in the advisory is definitive: "shift exponent 32 is too large for 32-bit type 'UInt32'". Consequently, the _inBuf buffer is allocated as a single byte. Subsequently, ReadStream_FALSE writes up to 256 MB of attacker-controlled data—calculated as (size_t)numChunks << BlockSizeLog—into that byte, overwriting the adjacent heap memory.

From Heap Overwrite to Execution Control

Debugger analysis in the advisory reveals the precise geometry of the overflow. The CInStream object occupies 304 bytes (0x130) and is allocated immediately following _inBuf. The first Read() call writes 64 KB (kBlockSize) of crafted data; after the first 304 bytes, it overwrites the stream object's vtable pointer. When the code attempts to dispatch via the vtable during the second Read() call, it executes the address specified by the attacker.

The researcher technically classified this mechanism as a vtable hijack and documented it step-by-step, proving it is a deterministic chain rather than a random crash. On x64 systems with at least 16 GB of RAM, the 8 GB allocation for _outBuf may succeed, but the vulnerability in _inBuf remains. On systems with insufficient RAM, the failed 8 GB allocation triggers an exception—a change in behavior, but not a reliable mitigation.

The "File Format Chameleon": Why Extensions Offer No Protection

The handler registration mechanism in 7-Zip, specifically REGISTER_ARC_I at line 2889 of NtfsHandler.cpp, configures the NTFS handler for signature-based activation using the NTFS string at offset 3. If a user renames a crafted image to invoice.zip, backup.7z, or document.rar, the extension-based parser initially rejects the file. However, the signature-based fallback mechanism identifies the NTFS header and passes the file to the vulnerable handler.

This behavior has immediate implications for automated security pipelines. Sandboxes, EDRs, antivirus solutions, and cloud scanning services that route files based on extensions—or use extensions as a proxy for MIME types—will process the file using the incorrect parser. Attackers do not need to convince victims to manually rename files; any upload, email attachment, or downloaded archive with a common extension can trigger the vulnerable path.

"A heap buffer overflow vulnerability exists in the NTFS archive handler in 7-Zip that can lead to code execution via vtable hijack" — GitHub Security Lab, advisory GHSL-2026-140

Remediation and Mitigation

  1. Update immediately to 7-Zip 26.01, released April 27, 2026. Verify your current version via Help > About; note that package managers (winget, Chocolatey, apt) may experience distribution lags not quantified in the advisory.
  2. Disable the automatic opening of extracted archives and configure 7-Zip to extract into isolated temporary folders to reduce the accidental trigger surface.
  3. Review corporate file processing pipelines: Sandboxes, email gateways, and cloud antimalware services that rely on extensions for routing must be tested against files containing NTFS signatures and false extensions.
  4. Enable ASLR and Control Flow Guard (CFG) on Windows where applicable. While the advisory demonstrates a successful vtable hijack, these mitigations increase exploitation complexity without entirely eliminating the risk.

Response Timeline and Exposure Windows

The advisory timeline shows a three-day interval between the private report (April 24) and the fix (April 27), a rapid technical response. However, the public disclosure on May 22, 2026, creates a different risk profile: those who updated by late April are protected, while those remaining on version 26.00—or earlier—operated for nearly four weeks with an available but unapplied patch. While the brief mentions no known in-the-wild exploits, the availability of a complete Python PoC lowers the technical barrier for developing functional exploits.

Researcher Jaroslav Lobačevski, active in the GitHub Security Lab as @JarLob, developed a proof-of-concept that generates sparse NTFS images: 512 MB apparent size, approximately 8 KB on disk, with manually crafted boot sectors and MFT records. The resulting poc_ntfs_sparse.ntfs is functional and verified via UBSan and debuggers, moving beyond theoretical risk.

The Failure of Extension-Based Filtering

The technical lesson here extends beyond 7-Zip. This incident demonstrates how the "block by extension" paradigm—still prevalent in gateways, DLP, and sandboxes—fails when a format contains an internal signature detectable independently of its container. The 7-Zip NTFS parser is not the first, nor will it be the last, to implement signature-based fallback. However, the combination of deterministic under-allocation, controlled overflow, and execution hijacking makes it a landmark case for defense-in-depth design.

For security operators, the priority is not just patching but verifying file routing within their pipelines. If a system decides "this is a .zip, use the zip parser" without accounting for signature fallbacks, it possesses a structural blind spot. The solution is not to abandon compressed formats, but to recognize that an extension is merely metadata, not identity.

Information is based on the cited advisory and is current as of the publication date.

Sources