new file mode 100644
@@ -0,0 +1,136 @@
+From 581a2f3ac9c6f96a26324f6b2c8c11415fd0d452 Mon Sep 17 00:00:00 2001
+From: Christian Brabandt <cb@256bit.org>
+Date: Fri, 24 Jul 2026 17:43:51 +0200
+Subject: [PATCH] patch 9.2.0847: [security]: vimball: code execution via
+ .VimballRecord file
+
+Problem: [security]: vimball: code execution via .VimballRecord file
+ (tdjackey)
+Solution: Forbid arbitrary commands, fix broken directory deletion code,
+ refactor code
+
+Github Security Advisory:
+https://github.com/vim/vim/security/advisories/GHSA-r22p-fhw4-84p2
+
+Signed-off-by: Christian Brabandt <cb@256bit.org>
+
+CVE: CVE-2026-73076
+Upstream-Status: Backport from https://github.com/vim/vim/commit/581a2f3ac9c6f96a26324f6b2c8c11415fd0d452
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ runtime/autoload/vimball.vim | 58 ++++++++++++++++++++++--------------
+ 1 file changed, 35 insertions(+), 23 deletions(-)
+
+diff --git a/runtime/autoload/vimball.vim b/runtime/autoload/vimball.vim
+index 6456984411..b206abef10 100644
+--- a/runtime/autoload/vimball.vim
++++ b/runtime/autoload/vimball.vim
+@@ -270,6 +270,13 @@ fun! vimball#Vimball(really,...)
+ let fenc = substitute(getline(linenr+1),'^\d\+\s*\(\S\{-}\)$','\1','')
+ let filecnt = filecnt + 1
+ " call Decho("fname<".fname."> fsize=".fsize." filecnt=".filecnt. " fenc=".fenc)
++ if fname =~? '\%(^\|/\)\.VimballRecord$'
++ echomsg "(Vimball) Forbidding .VimballRecord filename, aborting..."
++ exe "tabn ".curtabnr
++ bw! Vimball
++ call s:ChgDir(curdir)
++ return
++ endif
+
+ if a:really
+ echomsg "extracted <".fname.">: ".fsize." lines"
+@@ -309,7 +316,7 @@ fun! vimball#Vimball(really,...)
+ else
+ call mkdir(dirname)
+ endif
+- call s:RecordInVar(home,"rmdir('".dirname."')")
++ call s:RecordDirInVar(dirname)
+ endif
+ endwhile
+ endif
+@@ -343,7 +350,7 @@ fun! vimball#Vimball(really,...)
+ exe "silent w! ".fnameescape(fnamepath)
+ endif
+ echo "wrote ".fnameescape(fnamepath)
+- call s:RecordInVar(home,"call delete('".fnamepath."')")
++ call s:RecordInVar(fnamepath)
+ endif
+
+ " return to tab with vimball
+@@ -464,11 +471,17 @@ fun! vimball#RmVimball(...)
+ let s:VBRstring= substitute(exestring,'call delete(','','g')
+ let s:VBRstring= substitute(s:VBRstring,"[')]",'','g')
+ " call Decho("exe ".exestring)
+- sil! keepalt keepjumps exe exestring
++ let nr_files= 0
++ for line in split(exestring, '|')
++ if line !~ '^call delete(''[^'']\{-}''\(,"d"\)\?)$'
++ echomsg "ignoring .VimballRecord entry: " line
++ else
++ sil! keepalt keepjumps exe line
++ let nr_files+= 1
++ endif
++ endfor
+ sil! keepalt keepjumps d
+- let exestring= strlen(substitute(exestring,'call delete(.\{-})|\=',"D","g"))
+-" call Decho("exestring<".exestring.">")
+- echomsg "removed ".exestring." files"
++ echomsg "removed ".nr_files." files"
+ else
+ let s:VBRstring= ''
+ let curfile = substitute(curfile,'\.vmb','','')
+@@ -622,23 +635,22 @@ fun! s:ChgDir(newdir)
+ endfun
+
+ " ---------------------------------------------------------------------
+-" s:RecordInVar: record a un-vimball command in the .VimballRecord file {{{2
+-fun! s:RecordInVar(home,cmd)
+-" call Dfunc("RecordInVar(home<".a:home."> cmd<".a:cmd.">)")
+- if a:cmd =~ '^rmdir'
+-" if !exists("s:recorddir")
+-" let s:recorddir= substitute(a:cmd,'^rmdir',"call s:Rmdir",'')
+-" else
+-" let s:recorddir= s:recorddir."|".substitute(a:cmd,'^rmdir',"call s:Rmdir",'')
+-" endif
+- elseif !exists("s:recordfile")
+- let s:recordfile= a:cmd
+- else
+- let s:recordfile= s:recordfile."|".a:cmd
++" s:RecordInVar: record a un-vimball file deletion in the .VimballRecord file {{{2
++fun! s:RecordInVar(file)
++ if !exists("s:recordfile")
++ let s:recordfile=[]
+ endif
+-" call Dret("RecordInVar : s:recordfile<".(exists("s:recordfile")? s:recordfile : "")."> s:recorddir<".(exists("s:recorddir")? s:recorddir : "").">")
++ call add(s:recordfile, $'call delete({string(a:file)})')
+ endfun
+
++" s:RecordDirInVar: record a un-vimball dir deletion in the .VimballRecord file {{{2
++fun! s:RecordDirInVar(dir)
++ if !exists("s:recorddir")
++ let s:recorddir = []
++ endif
++ call add(s:recorddir, $'call delete({string(a:dir)},"d")')
++ endfun
++
+ " ---------------------------------------------------------------------
+ " s:RecordInFile: {{{2
+ fun! s:RecordInFile(home)
+@@ -660,11 +672,11 @@ fun! s:RecordInFile(home)
+ setlocal ma
+ $
+ if exists("s:recordfile") && exists("s:recorddir")
+- let cmd= cmd.s:recordfile."|".s:recorddir
++ let cmd= cmd.join(s:recordfile, '|')."|".join(s:recorddir, '|')
+ elseif exists("s:recorddir")
+- let cmd= cmd.s:recorddir
++ let cmd= cmd.join(s:recorddir, '|')
+ elseif exists("s:recordfile")
+- let cmd= cmd.s:recordfile
++ let cmd= cmd.join(s:recordfile, '|')
+ else
+ " call Dret("s:RecordInFile : neither recordfile nor recorddir exist")
+ return
+--
+2.50.1
+
@@ -55,6 +55,7 @@ SRC_URI = "git://github.com/vim/vim.git;branch=master;protocol=https \
file://CVE-2026-73074.patch \
file://CVE-2026-73077.patch \
file://CVE-2026-73078.patch \
+ file://CVE-2026-73076.patch \
"
PV .= ".1683"
Pick the patch from [1], also referenced in the NVD report [2]. [1] https://github.com/vim/vim/commit/581a2f3ac9c6f96a26324f6b2c8c11415fd0d452 [2] https://nvd.nist.gov/vuln/detail/CVE-2026-73076 Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> --- .../vim/files/CVE-2026-73076.patch | 136 ++++++++++++++++++ meta/recipes-support/vim/vim.inc | 1 + 2 files changed, 137 insertions(+) create mode 100644 meta/recipes-support/vim/files/CVE-2026-73076.patch