patch 9.1.1947: [security]: Windows: Vim may execute commands from current 
directory

Commit: 
https://github.com/vim/vim/commit/083ec6d9a3b7b09006e0ce69ac802597d25856d6
Author: Christian Brabandt <[email protected]>
Date:   Tue Nov 25 22:45:58 2025 +0100

    patch 9.1.1947: [security]: Windows: Vim may execute commands from current 
directory
    
    Problem:  [security]: Windows: Vim may execute commands from current
              directory (Simon Zuckerbraun)
    Solution: Set the $NoDefaultCurrentDirectoryInExePath before running
              external commands.
    
    Github Advisory:
    https://github.com/vim/vim/security/advisories/GHSA-g77q-xrww-p834
    
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 0b5215d7e..5f51af3ad 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2711,13 +2711,15 @@ executable({expr})                                      
*executable()*
                then the name is also tried without adding an extension.
                On MS-Windows it only checks if the file exists and is not a
                directory, not if it's really executable.
+
                On MS-Windows an executable in the same directory as the Vim
                executable is always found.  Since this directory is added to
                $PATH it should also work to execute it |win32-PATH|.
                                        *NoDefaultCurrentDirectoryInExePath*
                On MS-Windows an executable in Vim's current working directory
                is also normally found, but this can be disabled by setting
-               the $NoDefaultCurrentDirectoryInExePath environment variable.
+               the `$NoDefaultCurrentDirectoryInExePath` environment variable.
+               This is always done for |:!| commands, for security reasons.
 
                The result is a Number:
                        1       exists
diff --git a/src/os_win32.c b/src/os_win32.c
index 182d005aa..0a25d4850 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -5483,6 +5483,21 @@ mch_call_shell_terminal(
     return retval;
 }
 #endif
+/* Restore a previous environment variable value, or unset it if NULL.
+ * 'must_free' indicates whether 'old_value' was allocated.
+ */
+    static void
+restore_env_var(char_u *name, char_u *old_value, int must_free)
+{
+    if (old_value != NULL)
+    {
+       vim_setenv(name, old_value);
+       if (must_free)
+           vim_free(old_value);
+       return;
+    }
+    vim_unsetenv(name);
+}
 
 /*
  * Either execute a command by calling the shell or start a new shell
@@ -5495,6 +5510,8 @@ mch_call_shell(
     int                x = 0;
     int                tmode = cur_tmode;
     WCHAR      szShellTitle[512];
+    int                must_free;
+    char_u     *oldval;
 
 #ifdef FEAT_EVAL
     ch_log(NULL, "executing shell command: %s", cmd);
@@ -5519,6 +5536,11 @@ mch_call_shell(
            }
        }
     }
+    // do not execute anything from the current directory by setting the
+    // environemnt variable $NoDefaultCurrentDirectoryInExePath
+    oldval = vim_getenv((char_u *)"NoDefaultCurrentDirectoryInExePath",
+           &must_free);
+    vim_setenv((char_u *)"NoDefaultCurrentDirectoryInExePath", (char_u *)"1");
 
     out_flush();
 
@@ -5552,6 +5574,8 @@ mch_call_shell(
            // Use a terminal window to run the command in.
            x = mch_call_shell_terminal(cmd, options);
            resettitle();
+           restore_env_var((char_u *)"NoDefaultCurrentDirectoryInExePath",
+                   oldval, must_free);
            return x;
        }
     }
@@ -5776,6 +5800,10 @@ mch_call_shell(
        }
     }
 
+    // Restore original value of NoDefaultCurrentDirectoryInExePath
+    restore_env_var((char_u *)"NoDefaultCurrentDirectoryInExePath",
+           oldval, must_free);
+
     if (tmode == TMODE_RAW)
     {
        // The shell may have messed with the mode, always set it.
diff --git a/src/testdir/test_terminal2.vim b/src/testdir/test_terminal2.vim
index dea2e1fc5..cb2ed5ebb 100644
--- a/src/testdir/test_terminal2.vim
+++ b/src/testdir/test_terminal2.vim
@@ -440,6 +440,14 @@ func Test_zz2_terminal_guioptions_bang()
   call writefile(contents, filename, 'D')
   call setfperm(filename, 'rwxrwx---')
 
+  if has("win32")
+    " should not execute anything below the current directory
+    let exitval = 1
+    execute printf(':!%s%s %d', prefix, filename, exitval)
+    call assert_equal(exitval, v:shell_error)
+    let prefix = '.\'
+  endif
+
   " Check if v:shell_error is equal to the exit status.
   let exitval = 0
   execute printf(':!%s%s %d', prefix, filename, exitval)
@@ -732,5 +740,40 @@ func Test_term_gettty()
   exe buf . 'bwipe'
 endfunc
 
+func Test_windows_external_cmd_in_cwd()
+  " Check that Vim does not execute anything from current directory
+  CheckMSWindows
+
+  " just in case
+  call system('rd /S /Q Xfolder')
+  call mkdir('Xfolder', 'R')
+  cd Xfolder
+
+  let contents = ['@echo off', 'echo filename1.txt:1:AAAA']
+  call writefile(contents, 'findstr.cmd')
+
+  let file1 = ['AAAA', 'THIS FILE SHOULD NOT BE FOUND']
+  let file2 = ['BBBB', 'THIS FILE SHOULD BE FOUND']
+
+  call writefile(file1, 'filename1.txt')
+  call writefile(file2, 'filename2.txt')
+
+  " use silent to avoid hit-enter-prompt
+  sil grep BBBB filename*.txt
+
+  call assert_equal('filename2.txt', @%)
+
+  let output = system('findstr BBBB filename*')
+  " Match trailing newline byte
+  call assert_match('filename2.txt:BBBB.', output)
+
+  set guioptions+=!
+
+  let output = system('findstr BBBB filename*')
+  call assert_match('filename2.txt:BBBB.', output)
+
+  cd -
+  set guioptions&
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 916bc2174..545ecd309 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1947,
 /**/
     1946,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vQYBD-00DK0f-W2%40256bit.org.

Raspunde prin e-mail lui