aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/deprecated.txt4
-rw-r--r--runtime/doc/lua.txt16
-rw-r--r--runtime/doc/news.txt5
-rw-r--r--runtime/doc/options.txt27
-rw-r--r--runtime/doc/vim_diff.txt5
-rw-r--r--runtime/lua/vim/_editor.lua1
-rw-r--r--runtime/lua/vim/secure.lua106
-rwxr-xr-xscripts/gen_vimdoc.py3
-rw-r--r--src/nvim/ex_cmds.c9
-rw-r--r--src/nvim/ex_docmd.c3
-rw-r--r--src/nvim/fileio.c3
-rw-r--r--src/nvim/globals.h5
-rw-r--r--src/nvim/lua/executor.c24
-rw-r--r--src/nvim/main.c33
-rw-r--r--src/nvim/mapping.c3
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/runtime.c2
-rw-r--r--src/nvim/testdir/test_startup.vim1
-rw-r--r--test/functional/lua/secure_spec.lua171
19 files changed, 366 insertions, 57 deletions
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index 5e6bc957a1..401ac87d90 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -128,10 +128,6 @@ NORMAL COMMANDS
OPTIONS
- *cpo-<* *:menu-<special>* *:menu-special* *:map-<special>* *:map-special*
`<>` notation is always enabled.
-- *'exrc'* *'ex'* Security risk: downloaded files could include
- a malicious .nvimrc or .exrc file. See 'secure'.
- Recommended alternative: define an autocommand in your
- |vimrc| to set options for a matching directory.
- 'gdefault' Enables the |:substitute| flag 'g' by default.
- *'fe'* 'fenc'+'enc' before Vim 6.0; no longer used.
- *'highlight'* *'hl'* Names of builtin |highlight-groups| cannot be changed.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index cab2f49d94..c5ede97725 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -2354,4 +2354,20 @@ parents({start}) *vim.fs.parents()*
Return: ~
(function) Iterator
+
+==============================================================================
+Lua module: secure *lua-secure*
+
+read({path}) *vim.secure.read()*
+ Attempt to read the file at {path} prompting the user if the file should
+ be trusted. The user's choice is persisted in a trust database at
+ $XDG_STATE_HOME/nvim/trust.
+
+ Parameters: ~
+ • {path} (string) Path to a file to read.
+
+ Return: ~
+ (string|nil) The contents of the given file if it exists and is
+ trusted, or nil otherwise.
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index d339df8479..42a5d7e7ee 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -39,6 +39,9 @@ NEW FEATURES *news-features*
The following new APIs or features were added.
+• |vim.secure.read()| reads a file and prompts the user if it should be
+ trusted and, if so, returns the file's contents.
+
• When using Nvim inside tmux 3.2 or later, the default clipboard provider
will now copy to the system clipboard. |provider-clipboard|
@@ -57,6 +60,8 @@ CHANGED FEATURES *news-changes*
The following changes to existing APIs or features add new behavior.
+• 'exrc' is no longer marked deprecated.
+
==============================================================================
REMOVED FEATURES *news-removed*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index fd76f11046..0895d980f5 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2264,6 +2264,20 @@ A jump table for the options with a short description can be found at |Q_op|.
This option is reset when the 'paste' option is set and restored when
the 'paste' option is reset.
+ *'exrc'* *'ex'* *'noexrc'* *'noex'*
+'exrc' 'ex' boolean (default off)
+ global
+ Enables the reading of .nvimrc and .exrc files in the current
+ directory.
+
+ The file is only sourced if the user indicates the file is trusted. If
+ it is, the SHA256 hash of the file contents and the full path of the
+ file are persisted to a trust database. The user is only prompted
+ again if the file contents change. See |vim.secure.read()|.
+
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
+
*'fileencoding'* *'fenc'* *E213*
'fileencoding' 'fenc' string (default: "")
local to buffer
@@ -5115,19 +5129,6 @@ A jump table for the options with a short description can be found at |Q_op|.
two letters (See |object-motions|). The default makes a section start
at the nroff macros ".SH", ".NH", ".H", ".HU", ".nh" and ".sh".
- *'secure'* *'nosecure'* *E523*
-'secure' boolean (default off)
- global
- When on, ":autocmd", shell and write commands are not allowed in
- ".nvimrc" and ".exrc" in the current directory and map commands are
- displayed. Switch it off only if you know that you will not run into
- problems, or when the 'exrc' option is off. On Unix this option is
- only used if the ".nvimrc" or ".exrc" is not owned by you. This can be
- dangerous if the systems allows users to do a "chown". You better set
- 'secure' at the end of your |init.vim| then.
- This option cannot be set from a |modeline| or in the |sandbox|, for
- security reasons.
-
*'selection'* *'sel'*
'selection' 'sel' string (default "inclusive")
global
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index fe6c28c809..b5222c9ddd 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -417,6 +417,8 @@ Options:
'jumpoptions' "view" tries to restore the |mark-view| when moving through
the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|.
'shortmess' the "F" flag does not affect output from autocommands
+ 'exrc' searches for ".nvimrc" or ".exrc" files. The user is prompted whether
+ to trust the file.
Shell:
Shell output (|:!|, |:make|, …) is always routed through the UI, so it
@@ -639,6 +641,9 @@ Options:
*'prompt'* *'noprompt'*
*'remap'* *'noremap'*
*'restorescreen'* *'rs'* *'norestorescreen'* *'nors'*
+ *'secure'*
+ Everything is allowed in 'exrc' files since they must be explicitly marked
+ trusted.
*'shelltype'*
*'shortname'* *'sn'* *'noshortname'* *'nosn'*
*'swapsync'* *'sws'*
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 0013f38d89..ad4dc20efb 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -36,6 +36,7 @@ for k, v in pairs({
ui = true,
health = true,
fs = true,
+ secure = true,
}) do
vim._submodules[k] = v
end
diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua
new file mode 100644
index 0000000000..341ff8df05
--- /dev/null
+++ b/runtime/lua/vim/secure.lua
@@ -0,0 +1,106 @@
+local M = {}
+
+--- Attempt to read the file at {path} prompting the user if the file should be
+--- trusted. The user's choice is persisted in a trust database at
+--- $XDG_STATE_HOME/nvim/trust.
+---
+---@param path (string) Path to a file to read.
+---
+---@return (string|nil) The contents of the given file if it exists and is
+--- trusted, or nil otherwise.
+function M.read(path)
+ vim.validate({ path = { path, 's' } })
+ local fullpath = vim.loop.fs_realpath(vim.fs.normalize(path))
+ if not fullpath then
+ return nil
+ end
+
+ local trust = {}
+ do
+ local f = io.open(vim.fn.stdpath('state') .. '/trust', 'r')
+ if f then
+ local contents = f:read('*a')
+ if contents then
+ for line in vim.gsplit(contents, '\n') do
+ local hash, file = string.match(line, '^(%S+) (.+)$')
+ if hash and file then
+ trust[file] = hash
+ end
+ end
+ end
+ f:close()
+ end
+ end
+
+ if trust[fullpath] == '!' then
+ -- File is denied
+ return nil
+ end
+
+ local contents
+ do
+ local f = io.open(fullpath, 'r')
+ if not f then
+ return nil
+ end
+ contents = f:read('*a')
+ f:close()
+ end
+
+ local hash = vim.fn.sha256(contents)
+ if trust[fullpath] == hash then
+ -- File already exists in trust database
+ return contents
+ end
+
+ -- File either does not exist in trust database or the hash does not match
+ local choice = vim.fn.confirm(
+ string.format('%s is not trusted.', fullpath),
+ '&ignore\n&view\n&deny\n&allow',
+ 1
+ )
+
+ if choice == 0 or choice == 1 then
+ -- Cancelled or ignored
+ return nil
+ elseif choice == 2 then
+ -- View
+ vim.cmd('new')
+ local buf = vim.api.nvim_get_current_buf()
+ local lines = vim.split(string.gsub(contents, '\n$', ''), '\n')
+ vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
+ vim.bo[buf].bufhidden = 'hide'
+ vim.bo[buf].buftype = 'nofile'
+ vim.bo[buf].swapfile = false
+ vim.bo[buf].modeline = false
+ vim.bo[buf].buflisted = false
+ vim.bo[buf].readonly = true
+ vim.bo[buf].modifiable = false
+ return nil
+ elseif choice == 3 then
+ -- Deny
+ trust[fullpath] = '!'
+ contents = nil
+ elseif choice == 4 then
+ -- Allow
+ trust[fullpath] = hash
+ end
+
+ do
+ local f, err = io.open(vim.fn.stdpath('state') .. '/trust', 'w')
+ if not f then
+ error(err)
+ end
+
+ local t = {}
+ for p, h in pairs(trust) do
+ t[#t + 1] = string.format('%s %s\n', h, p)
+ end
+ f:write(table.concat(t))
+ f:close()
+ end
+
+ return contents
+end
+
+return M
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index e77d3ea286..a720f055ed 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -131,6 +131,7 @@ CONFIG = {
'filetype.lua',
'keymap.lua',
'fs.lua',
+ 'secure.lua',
],
'files': [
'runtime/lua/vim/_editor.lua',
@@ -140,6 +141,7 @@ CONFIG = {
'runtime/lua/vim/filetype.lua',
'runtime/lua/vim/keymap.lua',
'runtime/lua/vim/fs.lua',
+ 'runtime/lua/vim/secure.lua',
],
'file_patterns': '*.lua',
'fn_name_prefix': '',
@@ -166,6 +168,7 @@ CONFIG = {
'filetype': 'vim.filetype',
'keymap': 'vim.keymap',
'fs': 'vim.fs',
+ 'secure': 'vim.secure',
},
'append_only': [
'shared.lua',
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index c6dd30e549..1efde7ef3f 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1134,8 +1134,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
int scroll_save = msg_scroll;
//
- // Disallow shell commands from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow shell commands in secure mode
//
if (check_secure()) {
return;
@@ -1477,8 +1476,7 @@ filterend:
/// @param flags may be SHELL_DOOUT when output is redirected
void do_shell(char *cmd, int flags)
{
- // Disallow shell commands from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow shell commands in secure mode
if (check_secure()) {
msg_end();
return;
@@ -3215,8 +3213,7 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true;
}
-/// @return true if the secure flag is set (.exrc or .vimrc in current directory)
-/// and also give an error message.
+/// @return true if the secure flag is set and also give an error message.
/// Otherwise, return false.
bool check_secure(void)
{
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index e0e4fa332f..0733bcf683 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4223,8 +4223,7 @@ theend:
static void ex_autocmd(exarg_T *eap)
{
- // Disallow autocommands from .exrc and .vimrc in current
- // directory for security reasons.
+ // Disallow autocommands in secure mode.
if (secure) {
secure = 2;
eap->errmsg = _(e_curdir);
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 6c5469d020..d6bc861c09 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -2211,8 +2211,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
return FAIL;
}
- // Disallow writing from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow writing in secure mode.
if (check_secure()) {
return FAIL;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 76f62fe267..130f3f6c48 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -489,8 +489,7 @@ EXTERN int stdin_fd INIT(= -1);
// true when doing full-screen output, otherwise only writing some messages.
EXTERN int full_screen INIT(= false);
-/// Non-zero when only "safe" commands are allowed, e.g. when sourcing .exrc or
-/// .vimrc in current directory.
+/// Non-zero when only "safe" commands are allowed
EXTERN int secure INIT(= 0);
/// Non-zero when changing text and jumping to another window or editing another buffer is not
@@ -864,7 +863,7 @@ EXTERN char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job"));
EXTERN char e_argreq[] INIT(= N_("E471: Argument required"));
EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &"));
EXTERN char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
-EXTERN char e_curdir[] INIT(= N_("E12: Command not allowed from exrc/vimrc in current dir or tag search"));
+EXTERN char e_curdir[] INIT(= N_("E12: Command not allowed in secure mode in current dir or tag search"));
EXTERN char e_command_too_recursive[] INIT(= N_("E169: Command too recursive"));
EXTERN char e_endif[] INIT(= N_("E171: Missing :endif"));
EXTERN char e_endtry[] INIT(= N_("E600: Missing :endtry"));
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 79cc3ed112..43a3b12a98 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -2193,3 +2193,27 @@ plain:
kv_printf(str, "<Lua %d>", ref);
return str.items;
}
+
+char *nlua_read_secure(const char *path)
+{
+ lua_State *const lstate = global_lstate;
+ lua_getglobal(lstate, "vim");
+ lua_getfield(lstate, -1, "secure");
+ lua_getfield(lstate, -1, "read");
+ lua_pushstring(lstate, path);
+ lua_call(lstate, 1, 1);
+
+ size_t len = 0;
+ const char *contents = lua_tolstring(lstate, -1, &len);
+ char *buf = NULL;
+ if (contents != NULL) {
+ // Add one to include trailing null byte
+ buf = xcalloc(len + 1, sizeof(char));
+ memcpy(buf, contents, len + 1);
+ }
+
+ // Pop return value, "vim", and "secure"
+ lua_pop(lstate, 3);
+
+ return buf;
+}
diff --git a/src/nvim/main.c b/src/nvim/main.c
index d8570f49eb..a369ca0256 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -1989,35 +1989,22 @@ static void source_startup_scripts(const mparm_T *const parmp)
do_system_initialization();
if (do_user_initialization()) {
- // Read initialization commands from ".vimrc" or ".exrc" in current
+ // Read initialization commands from ".nvimrc" or ".exrc" in current
// directory. This is only done if the 'exrc' option is set.
- // Because of security reasons we disallow shell and write commands
- // now, except for unix if the file is owned by the user or 'secure'
- // option has been reset in environment of global "exrc" or "vimrc".
// Only do this if VIMRC_FILE is not the same as vimrc file sourced in
// do_user_initialization.
-#if defined(UNIX)
- // If vimrc file is not owned by user, set 'secure' mode.
- if (!os_file_owned(VIMRC_FILE)) // NOLINT(readability/braces)
-#endif
- secure = p_secure;
-
- if (do_source(VIMRC_FILE, true, DOSO_VIMRC) == FAIL) {
-#if defined(UNIX)
- // if ".exrc" is not owned by user set 'secure' mode
- if (!os_file_owned(EXRC_FILE)) {
- secure = p_secure;
- } else {
- secure = 0;
+ char *str = nlua_read_secure(VIMRC_FILE);
+ if (str != NULL) {
+ do_source_str(str, VIMRC_FILE);
+ xfree(str);
+ } else {
+ str = nlua_read_secure(EXRC_FILE);
+ if (str != NULL) {
+ do_source_str(str, EXRC_FILE);
+ xfree(str);
}
-#endif
- (void)do_source(EXRC_FILE, false, DOSO_NONE);
}
}
- if (secure == 2) {
- need_wait_return = true;
- }
- secure = 0;
}
TIME_MSG("sourcing vimrc file(s)");
}
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 9b10ea901e..76a646083e 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -2446,8 +2446,7 @@ void ex_abbreviate(exarg_T *eap)
/// ":map" and friends.
void ex_map(exarg_T *eap)
{
- // If we are sourcing .exrc or .vimrc in current directory we
- // print the mappings for security reasons.
+ // If we are in a secure mode we print the mappings for security reasons.
if (secure) {
secure = 2;
msg_outtrans(eap->cmd);
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index dc0561d560..1cf8ab3253 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2007,7 +2007,7 @@ return {
},
{
full_name='secure',
- short_desc=N_("mode for reading .vimrc in current dir"),
+ short_desc=N_("No description"),
type='bool', scope={'global'},
secure=true,
varname='p_secure',
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index e1a2483438..db8dc04907 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -1930,7 +1930,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
cookie.fp = fopen_noinh_readbin(fname_exp);
if (cookie.fp == NULL && check_other) {
- // Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
+ // Try again, replacing file name ".nvimrc" by "_nvimrc" or vice versa,
// and ".exrc" by "_exrc" or vice versa.
p = path_tail(fname_exp);
if ((*p == '.' || *p == '_')
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index f9f7c5b492..42467c5508 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -1024,6 +1024,7 @@ endfunc
" Test for using the 'exrc' option
func Test_exrc()
+ throw 'Skipped: Nvim requires user input for the exrc option'
let after =<< trim [CODE]
call assert_equal(1, &exrc)
call assert_equal(1, &secure)
diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua
new file mode 100644
index 0000000000..c348526d65
--- /dev/null
+++ b/test/functional/lua/secure_spec.lua
@@ -0,0 +1,171 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+
+local eq = helpers.eq
+local clear = helpers.clear
+local command = helpers.command
+local pathsep = helpers.get_pathsep()
+local iswin = helpers.iswin()
+local curbufmeths = helpers.curbufmeths
+local exec_lua = helpers.exec_lua
+local feed_command = helpers.feed_command
+local feed = helpers.feed
+local funcs = helpers.funcs
+local pcall_err = helpers.pcall_err
+
+describe('vim.secure', function()
+ describe('read()', function()
+ local xstate = 'Xstate'
+
+ setup(function()
+ helpers.mkdir_p(xstate .. pathsep .. (iswin and 'nvim-data' or 'nvim'))
+ end)
+
+ teardown(function()
+ helpers.rmdir(xstate)
+ end)
+
+ before_each(function()
+ helpers.write_file('Xfile', [[
+ let g:foobar = 42
+ ]])
+ clear{env={XDG_STATE_HOME=xstate}}
+ end)
+
+ after_each(function()
+ os.remove('Xfile')
+ helpers.rmdir(xstate)
+ end)
+
+ it('works', function()
+ local screen = Screen.new(80, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {bold = true, reverse = true},
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen},
+ [4] = {reverse = true},
+ })
+
+ local cwd = funcs.getcwd()
+
+ -- Need to use feed_command instead of exec_lua because of the confirmation prompt
+ feed_command([[lua vim.secure.read('Xfile')]])
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ :lua vim.secure.read('Xfile') |
+ {3:]] .. cwd .. pathsep .. [[Xfile is untrusted}{MATCH:%s+}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
+ ]]}
+ feed('d')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust))
+ eq(helpers.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
+
+ os.remove(funcs.stdpath('state') .. pathsep .. 'trust')
+
+ feed_command([[lua vim.secure.read('Xfile')]])
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ :lua vim.secure.read('Xfile') |
+ {3:]] .. cwd .. pathsep .. [[Xfile is untrusted}{MATCH:%s+}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
+ ]]}
+ feed('a')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ local hash = funcs.sha256(helpers.read_file('Xfile'))
+ trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust))
+ eq(helpers.NIL, exec_lua([[vim.secure.read('Xfile')]]))
+
+ os.remove(funcs.stdpath('state') .. pathsep .. 'trust')
+
+ feed_command([[lua vim.secure.read('Xfile')]])
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ :lua vim.secure.read('Xfile') |
+ {3:]] .. cwd .. pathsep .. [[Xfile is untrusted}{MATCH:%s+}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
+ ]]}
+ feed('i')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ -- Trust database is not updated
+ trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(nil, trust)
+
+ feed_command([[lua vim.secure.read('Xfile')]])
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ :lua vim.secure.read('Xfile') |
+ {3:]] .. cwd .. pathsep .. [[Xfile is untrusted}{MATCH:%s+}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
+ ]]}
+ feed('v')
+ screen:expect{grid=[[
+ ^ let g:foobar = 42 |
+ {1:~ }|
+ {1:~ }|
+ {2:]] .. cwd .. pathsep .. [[Xfile [RO]{MATCH:%s+}|
+ |
+ {1:~ }|
+ {4:[No Name] }|
+ |
+ ]]}
+
+ -- Trust database is not updated
+ trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(nil, trust)
+
+ -- Cannot write file
+ pcall_err(command, 'write')
+ eq(false, curbufmeths.get_option('modifiable'))
+ end)
+ end)
+end)