diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index e6437a354c..a07682c97d 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -63,7 +63,10 @@ DIAGNOSTICS EDITOR -• todo +• |vim.secure.read()| now removes the choice "(a)llow" from the prompt reply for + files unlisted in the user's trust database, and thus requires the user to + choose (v)iew then run `:trust`. Previously the user would be able to press + the single key 'a' to execute the arbitrary execution immediately. EVENTS diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua index c3731bf595..6e800e2c1a 100644 --- a/runtime/lua/vim/secure.lua +++ b/runtime/lua/vim/secure.lua @@ -121,18 +121,16 @@ function M.read(path) return contents end - local dir_msg = '' + local dir_msg = ' To enable it, choose (v)iew then run `:trust`.' + local choices = '&ignore\n&view\n&deny' if hash == 'directory' then dir_msg = ' DIRECTORY trust is decided only by its name, not its contents.' + choices = '&ignore\n&view\n&deny\n&allow' end -- File either does not exist in trust database or the hash does not match - local ok, result = pcall( - vim.fn.confirm, - string.format('%s is not trusted.%s', fullpath, dir_msg), - '&ignore\n&view\n&deny\n&allow', - 1 - ) + local ok, result = + pcall(vim.fn.confirm, string.format('%s is not trusted.%s', fullpath, dir_msg), choices, 1) if not ok and result ~= 'Keyboard interrupt' then error(result) @@ -147,7 +145,7 @@ function M.read(path) -- Deny trust[fullpath] = '!' contents = nil - elseif result == 4 then + elseif hash == 'directory' and result == 4 then -- Allow trust[fullpath] = hash end diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 65760bf68c..7d03a0e7b0 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -1200,9 +1200,11 @@ describe('user config init', function() VIMRUNTIME = os.getenv('VIMRUNTIME'), }, }) - screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:') }) - -- `i` to enter Terminal mode, `a` to allow - feed('ia') + screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny:') }) + -- `i` to enter Terminal mode, `v` to view then `:trust` + feed('iv') + feed(':trust') + feed(':q') screen:expect([[ ^ | ~ |*4 @@ -1219,8 +1221,8 @@ describe('user config init', function() %s%s| -- TERMINAL -- | ]], - filename, - string.rep(' ', 50 - #filename) + '---', + string.rep(' ', 50 - #'---') )) clear { args_rm = { '-u' }, env = xstateenv } @@ -1239,7 +1241,8 @@ describe('user config init', function() setup_exrc_file('.nvim.lua') setup_exrc_file('../.exrc') clear { args_rm = { '-u' }, env = xstateenv } - local screen = Screen.new(50, 8) + -- use a screen wide width to avoid wrapping the word `.exrc`, `.nvim.lua` below. + local screen = Screen.new(500, 8) screen._default_attr_ids = nil fn.jobstart({ nvim_prog }, { term = true, @@ -1249,13 +1252,36 @@ describe('user config init', function() }) -- current directory exrc is found first screen:expect({ any = '.nvim.lua' }) - screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:'), unchanged = true }) - feed('ia') + screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny:'), unchanged = true }) + feed('iv') -- after that the exrc in the parent directory - screen:expect({ any = '.exrc' }) - screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:'), unchanged = true }) - feed('a') + screen:expect({ any = '.exrc', unchanged = true }) + screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny:'), unchanged = true }) + feed('v') + + -- trust .exrc + feed(':trust') + screen:expect({ any = 'Allowed ".*' .. pathsep .. '%.exrc" in trust database.' }) + feed(':q') + -- trust .nvim.lua + feed(':trust') + screen:expect({ any = 'Allowed ".*' .. pathsep .. '%.nvim%.lua" in trust database.' }) + feed(':q') + -- no exrc file is executed + feed(':echo g:exrc_count') + screen:expect({ any = 'E121: Undefined variable: g:exrc_count' }) + + -- restart nvim + feed(':restart') + screen:expect([[ + ^{MATCH: +}| + ~{MATCH: +}|*4 + [No Name]{MATCH: +}0,0-1{MATCH: +}All| + {MATCH: +}| + -- TERMINAL --{MATCH: +}| + ]]) + -- a total of 2 exrc files are executed feed(':echo g:exrc_count') screen:expect({ any = '2' }) diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua index 71e2ff9d3d..fdf7f1e9a6 100644 --- a/test/functional/lua/secure_spec.lua +++ b/test/functional/lua/secure_spec.lua @@ -55,7 +55,9 @@ describe('vim.secure', function() }) local cwd = fn.getcwd() - local msg = cwd .. pathsep .. 'Xfile is not trusted.' + local msg = cwd + .. pathsep + .. 'Xfile is not trusted. To enable it, choose (v)iew then run `:trust`.' if #msg >= screen._width then pending('path too long') return @@ -69,7 +71,7 @@ describe('vim.secure', function() {2:{MATCH: +}}| :lua vim.secure.read('Xfile'){MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}| - {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| + {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| ]]) feed('d') screen:expect([[ @@ -91,14 +93,21 @@ describe('vim.secure', function() {2:{MATCH: +}}| :lua vim.secure.read('Xfile'){MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}| - {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| + {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| ]]) - feed('a') + feed('v') + feed(':trust') screen:expect([[ - ^{MATCH: +}| - {1:~{MATCH: +}}|*6 + ^let g:foobar = 42{MATCH: +}| + {1:~{MATCH: +}}|*2 + {2:]] .. fn.fnamemodify(cwd, ':~') .. pathsep .. [[Xfile [RO]{MATCH: +}}| {MATCH: +}| + {1:~{MATCH: +}}| + {4:[No Name]{MATCH: +}}| + Allowed "]] .. cwd .. pathsep .. [[Xfile" in trust database.{MATCH: +}| ]]) + -- close the split for the next test below. + feed(':q') local hash = fn.sha256(assert(read_file('Xfile'))) trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) @@ -114,7 +123,7 @@ describe('vim.secure', function() {2:{MATCH: +}}| :lua vim.secure.read('Xfile'){MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}| - {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| + {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| ]]) feed('i') screen:expect([[ @@ -133,7 +142,7 @@ describe('vim.secure', function() {2:{MATCH: +}}| :lua vim.secure.read('Xfile'){MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}| - {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| + {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| ]]) feed('v') screen:expect([[