Vim users should update immediately: a newly assigned vulnerability, CVE-2026-28420, allows a heap-based buffer overflow write and an out-of-bounds read in Vim’s terminal emulator when processing extreme Unicode combining sequences; the upstream fix appears in Vim patch v9.2.0076. (github.com)
Vim remains one of the most widely used terminal text editors across developer workstations, servers, containers, and build systems. Its built‑in terminal emulator (accessed with the :terminal command) renders output from processes and must faithfully handle Unicode and combining characters emitted by terminal applications. A recently disclosed defect shows how assumptions about the maximum bytes per terminal "cell" can be broken by Unicode supplementary-plane combining characters, producing memory corruption.
The vulnerability was assigned CVE‑2026‑28420 and publicly documented on February 27, 2026. The National Vulnerability Database (NVD) and multiple open-source vulnerability databases record the same root cause: prior to patch v9.2.0076 Vim’s terminal handling could be coerced into overwriting heap buffers and reading past array bounds when presented with the maximum allowed number of combining characters from supplementary planes. Upstream remediation is in patch v9.2.0076.
Community security lists and OSS channels published details and coordinated disclosure concurrently with the upstream fix. WindowsForum’s recent activity tracker flagged a cluster of Vim security advisories and patches in the same timeframe, indicating an active patching wave across several distinct Vim CVEs; this broader activity underscores the need for maintainers to audit Vim versions across their fleets.
In short: update Vim, add the new tests to your CI, and avoid running untrusted output inside :terminal until your environment is patched.
Source: MSRC Security Update Guide - Microsoft Security Response Center
Background / Overview
Vim remains one of the most widely used terminal text editors across developer workstations, servers, containers, and build systems. Its built‑in terminal emulator (accessed with the :terminal command) renders output from processes and must faithfully handle Unicode and combining characters emitted by terminal applications. A recently disclosed defect shows how assumptions about the maximum bytes per terminal "cell" can be broken by Unicode supplementary-plane combining characters, producing memory corruption.The vulnerability was assigned CVE‑2026‑28420 and publicly documented on February 27, 2026. The National Vulnerability Database (NVD) and multiple open-source vulnerability databases record the same root cause: prior to patch v9.2.0076 Vim’s terminal handling could be coerced into overwriting heap buffers and reading past array bounds when presented with the maximum allowed number of combining characters from supplementary planes. Upstream remediation is in patch v9.2.0076.
What exactly is wrong? Technical summary
Vulnerable code path: handle_pushline in src/terminal.c
The flaw resides in the terminal output handler, specifically the function handle_pushline() in src/terminal.c. Two related defects were fixed:- A heap-based buffer overflow WRITE: The code used ga_grow() to allocate space for UTF‑8 encoded bytes using the macro MB_MAXBYTES (21 bytes assumed per cell). That value assumed characters would remain inside the Basic Multilingual Plane (BMP), which fits within 3 bytes in UTF‑8. However, in practice a single terminal cell can contain up to VTERM_MAX_CHARS_PER_CELL characters from supplementary planes, each encoded as 4 bytes in UTF‑8. When those extreme combinations occur, the required space exceeds the old allocation (for example 6×4 bytes = 24 bytes), producing a 3‑byte overflow during conversion. (github.com)
- An out‑of‑bounds read: A loop that iterates over the characters stored in the per‑cell vterm_screen_cell_t.chars array did not cap the index correctly. When a cell was fully populated with characters, the loop condition could read index 6 of a 6‑element array (i.e., a read past the final element). The combination of write overflow and unchecked reads increases the practical risk: a crash is trivial, and memory corruption scenarios are plausible.
Why Unicode combining characters matter here
Terminal cells are allowed to contain base characters plus combining marks; for example, a Latin letter can be followed by multiple accent marks and diacritics that should render as a single visual cell. The terminal code in Vim supports multiple combining characters per cell—VTERM_MAX_CHARS_PER_CELL controls how many—but UTF‑8 encoding length depends on the Unicode code point.- Characters in the BMP: up to 3 bytes in UTF‑8 (historically the most common case).
- Characters in the supplementary planes: 4 bytes in UTF‑8.
Impact and exploitability
What an attacker needs
This is not a remote network service; exploitation requires the attacker to control what is printed inside a Vim :terminal buffer. Practically, that means:- The attacker must run a program (or control a program) whose output appears inside a user’s Vim terminal buffer, or
- The attacker must influence a local or remote process feeding the terminal session (for example, by controlling the output of a shell, build script, or remote command executed inside the terminal).
Realistic consequences
- Denial of Service (DoS): A crash is the simplest result—a crafted output stream containing extreme combining sequences will reliably crash or terminate the running Vim process.
- Memory corruption: The heap overflow and OOB read can produce memory corruption beyond a simple crash. In constrained scenarios this could theoretically be turned into more powerful outcomes, including process‑level code execution, but achieving reliable arbitrary code execution would depend on platform, build options, memory layout, mitigations (ASLR, heap hardening), and whether the target binary was built with exploitable options. The advisory credits two reporters who supplied a proof‑of‑concept; upstream fixed the code and added tests. (github.com)
Who is affected
- All users running Vim versions prior to v9.2.0076 with the terminal feature enabled are potentially affected. This includes many Linux, macOS, and Windows builds that include the :terminal feature. Distribution packages and third‑party binaries commonly ship Vim; maintainers should review whether their distributed packages include the patched version. Upstream metadata and advisories link CVE‑2026‑28420 to the GitHub advisory GHSA‑rvj2‑jrf9‑2phg and the v9.2.0076 release.
Vendor and upstream response
The Vim project published a patch as part of the 9.2.0076 release. The fix modifies src/terminal.c to:- Replace MB_MAXBYTES allocation with VTERM_MAX_CHARS_PER_CELL * 4 to ensure enough space for the worstcharacters rendered as four bytes each, and
- Add an explicit boundary check to the loop that reads per‑cell characters to prevent reading past the vterm array.
Community security lists and OSS channels published details and coordinated disclosure concurrently with the upstream fix. WindowsForum’s recent activity tracker flagged a cluster of Vim security advisories and patches in the same timeframe, indicating an active patching wave across several distinct Vim CVEs; this broader activity underscores the need for maintainers to audit Vim versions across their fleets.
Mitigation and detection
If you cannot immediately patch to v9.2.0076, follow these interim mitigations and detection steps.Immediate mitigations
- Avoid running untrusted processes in :terminal: Treat the :terminal buffer like any interactive terminal: do not run untrusted or unauthenticated binaries, build scripts, or compiler toolchains that might emit crafted combining sequences.
- Use a sandboxed environment: If you must run untrusted code, use containerization, strict seccomp profiles, or virtual machines so that a crashed Vim process or exploited process is isolated.
- Drop privileges where possible: Run Vim as an unprivileged user. The reported attack vector requires user interaction and is local; limiting privileges reduces post‑exploit impact.
Detection
- Crash monitoring: Look for repeated or reproducible Vim crashes correlated with terminal sessions. Systemd-coredump logs, journal entries, or crash reports might show consistent crash stacks pointing to terminal.c or handle_pushline().
- Audit terminal‑feeding processes: If you operate environments where users open remote shells or automated terminal sessions (e.g., CI job runners‑programming sessions), audit those inputs for unusual sequences of combining Unicode characters. While blind detection is noisy, unusual patterns from untrusted sources warrant attention.
- Instrument test suites: Upstream added test cases that generate maximal combining character sequences; incorporate similar tests into CI to ensure local builds are not vulnerable. The GitHub commit includes sample data and tests that can be adapted to local test harnesses. (github.com)
Recommended remediation steps (priority checklist)
- Update to Vim v9.2.0076 or later as soon as packages are available from upstream or your distribution packager. This is the only full fix for the specific memory‑safety defects described.
- For managed fleets, push the updated package across build systems, CI runners, developer workstations, and container base images. Treat this as a high‑priority maintenance update where :terminal is used.
- If you maintain your own Vim builds, pull the commit bb6de2105b160e729c34063 into your tree and rebuild; the commit includes tests and a clearly documented change. (github.com)
- Where patching is delayed, apply compensating controls: restrict running untrusted code in :terminal, run Vim as a non‑privileged user, and isolate sessions with containers or VMs.
- Add the upstream test sample (terminal_max_combining_chars.txt / test_terminal3.vim) into your regression suite so future builds are checked for the same class of error. (github.com)
Practical guidance for common platforms
Linux distributions and package managers
- Many mainstream distributions (Debian, Ubuntu, Fedora, Arch, etc.) mirror upstream Git tags and. Check your distribution’s package database for a patched vim package (v9.2.0076 or later). If distribution maintainers have not yet published the package, consider compiling from source with the upstream patch, or applying vendor‑supported backports. Upstream advisories indicate the fix is small and localized to src/terminal.c, making backporting feasible if you follow standard packaging practices.
Windows (gvim / vim for Windows)
- Windows builds produced by third‑party maintainers or the vim‑win32‑installer project will need to incorporate the upstream patch. Users of prepackaged Windows installers should watch for new installer builds that reference patch v9.2.0076. The GitHub release and advisory tags are the authoritative indicators that a build includes the fix. (github.com)
Container images and CI runners
- Many container images use lightweight Vim binaries for editing and scripting. Rebuild CI images and base containers that include Vim with the patched version. For ephemeral CI runners, ensure job definitions pull the updated base image, and scan images for installed package versions as part of image build pipelines.
Risk analysis: strengths and limitations of the fix
Strengths
- The upstream patch is targeted and small, addressing both the allocation size and the boundary check. It uses the defined VTERM_MAX_CHARS_PER_CELL constant to compute safe allocation and clamps the loop index, an approach sive programming and easy to audit. The inclusion of a test sample and a new test file improves the regression coverage for this class of Unicode‑related terminal handling bugs. (github.com)
- The vulnerability’s exploitability is limited by attack vector and required user interaction—this lowers systemic risk for remote compromise compared with network‑facing services.
Limitations and risks remaining
- The root cause is a typical assumption mismatch between character‑count limits and worst‑case encoding size. Other code paths that perform similar assumptions about MB_MAXBYTES or per‑cell allocations could exist elsewhere in the codebase; maintainers and downstream packagers should run audit tests for similar patterns. The quick fix addresses the symptoms in handle_pushline(), but other modules may still assume BMP‑only encodings.
- While local attack vectors reduce immediacy, automated or remote workflows that funnel attacker‑controlled output into a Vim terminal (for example, build agents that show build logs in a terminal buffer) can expose an organizational risk at scale. Environments that permit arbitrary developers or external contributors to trigger GUIless terminal outputs should consider additional safeguards.
- The potential for memory corruption to be elevated into reliable code execution depends heavily on platform mitigations (ASLR, stack canaries, heap hardening). Do not assume absence of an exploit implies zero risk—memory‑corruption defects should be treated as high‑priority to patch even when proof‑of‑concepts are limited to crash demonstration.
Testing and verification
To verify whether your installation is patched:- Check your installed Vim version: the patched release is v9.2.0076 or later.
- For source trees, confirm the presence of the commit changing ga_grow(...) to use VTERM_MAX_CHARS_PER_CELL * 4 and the adjusted loop condition in src/terminal.c. The commit message and diff are available in the upstream repo. (github.com)
- Optionally run the sample terminal_max_combining_chars.txt and test_terminal3.vim provided with the patch in a controlled environment and observe that the previously failing behavior no longer crashes the process. (github.com)
What system administrators and developers should tell users
- For end users: stop running untrusted programs inside Vim’s :terminal until you have updated to the patched Vim release. If you rely on the terminal feature extensively, update promptly.
- For developers and maintainers: prioritize deploying patched packages to developer workstations and CI runnges and local workstation images are rebuilt with the patched package.
- For security teams: add an entry to your vulnerability tracker with CVE‑2026‑28420, note affected populations (workstations and developer infrastructure with :terminal enabled), and schedule patch deployment. Monitor for crash reports that reference terminal.c as part of triage.
Final assessment
CVE‑2026‑28420 is a practical demonstration of how Unicode edge cases can break longstanding assumptions in terminal handling code. The fix upstream is small, well‑targeted, and includes regression tests; that makes remediation straightforward for most maintainers. However, the vulnerability underscores two persistent realities:- Even mature, well‑audited tools like Vim can carry latent memory‑safety issues when code assumes narrow character encodings or simplified character‑size math.
- Local or interactive features (like :terminal) create attack surfaces that are not eliminated by focusing solely on network‑facing services; automation and developer workflows can convert local vectors into organizational risk.
In short: update Vim, add the new tests to your CI, and avoid running untrusted output inside :terminal until your environment is patched.
Source: MSRC Security Update Guide - Microsoft Security Response Center