secure_spec.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local eq = t.eq
  5. local clear = n.clear
  6. local command = n.command
  7. local pathsep = n.get_pathsep()
  8. local is_os = t.is_os
  9. local api = n.api
  10. local exec_lua = n.exec_lua
  11. local feed_command = n.feed_command
  12. local feed = n.feed
  13. local fn = n.fn
  14. local stdpath = fn.stdpath
  15. local pcall_err = t.pcall_err
  16. local matches = t.matches
  17. local read_file = t.read_file
  18. describe('vim.secure', function()
  19. describe('read()', function()
  20. local xstate = 'Xstate'
  21. setup(function()
  22. clear { env = { XDG_STATE_HOME = xstate } }
  23. n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
  24. t.write_file(
  25. 'Xfile',
  26. [[
  27. let g:foobar = 42
  28. ]]
  29. )
  30. end)
  31. teardown(function()
  32. os.remove('Xfile')
  33. n.rmdir(xstate)
  34. end)
  35. it('works', function()
  36. local screen = Screen.new(80, 8)
  37. screen:set_default_attr_ids({
  38. [1] = { bold = true, foreground = Screen.colors.Blue1 },
  39. [2] = { bold = true, reverse = true },
  40. [3] = { bold = true, foreground = Screen.colors.SeaGreen },
  41. [4] = { reverse = true },
  42. })
  43. --- XXX: screen:expect() may fail if this path is too long.
  44. local cwd = fn.getcwd()
  45. -- Need to use feed_command instead of exec_lua because of the confirmation prompt
  46. feed_command([[lua vim.secure.read('Xfile')]])
  47. screen:expect {
  48. grid = [[
  49. |
  50. {1:~ }|*3
  51. {2: }|
  52. :lua vim.secure.read('Xfile') |
  53. {3:]]
  54. .. cwd
  55. .. pathsep
  56. .. [[Xfile is not trusted.}{MATCH:%s+}|
  57. {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
  58. ]],
  59. }
  60. feed('d')
  61. screen:expect {
  62. grid = [[
  63. ^ |
  64. {1:~ }|*6
  65. |
  66. ]],
  67. }
  68. local trust = read_file(stdpath('state') .. pathsep .. 'trust')
  69. eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust))
  70. eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
  71. os.remove(stdpath('state') .. pathsep .. 'trust')
  72. feed_command([[lua vim.secure.read('Xfile')]])
  73. screen:expect {
  74. grid = [[
  75. |
  76. {1:~ }|*3
  77. {2: }|
  78. :lua vim.secure.read('Xfile') |
  79. {3:]]
  80. .. cwd
  81. .. pathsep
  82. .. [[Xfile is not trusted.}{MATCH:%s+}|
  83. {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
  84. ]],
  85. }
  86. feed('a')
  87. screen:expect {
  88. grid = [[
  89. ^ |
  90. {1:~ }|*6
  91. |
  92. ]],
  93. }
  94. local hash = fn.sha256(read_file('Xfile'))
  95. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  96. eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust))
  97. eq(vim.NIL, exec_lua([[vim.secure.read('Xfile')]]))
  98. os.remove(stdpath('state') .. pathsep .. 'trust')
  99. feed_command([[lua vim.secure.read('Xfile')]])
  100. screen:expect {
  101. grid = [[
  102. |
  103. {1:~ }|*3
  104. {2: }|
  105. :lua vim.secure.read('Xfile') |
  106. {3:]]
  107. .. cwd
  108. .. pathsep
  109. .. [[Xfile is not trusted.}{MATCH:%s+}|
  110. {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
  111. ]],
  112. }
  113. feed('i')
  114. screen:expect {
  115. grid = [[
  116. ^ |
  117. {1:~ }|*6
  118. |
  119. ]],
  120. }
  121. -- Trust database is not updated
  122. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  123. eq(nil, trust)
  124. feed_command([[lua vim.secure.read('Xfile')]])
  125. screen:expect {
  126. grid = [[
  127. |
  128. {1:~ }|*3
  129. {2: }|
  130. :lua vim.secure.read('Xfile') |
  131. {3:]]
  132. .. cwd
  133. .. pathsep
  134. .. [[Xfile is not trusted.}{MATCH:%s+}|
  135. {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
  136. ]],
  137. }
  138. feed('v')
  139. screen:expect {
  140. grid = [[
  141. ^let g:foobar = 42 |
  142. {1:~ }|*2
  143. {2:]]
  144. .. fn.fnamemodify(cwd, ':~')
  145. .. pathsep
  146. .. [[Xfile [RO]{MATCH:%s+}}|
  147. |
  148. {1:~ }|
  149. {4:[No Name] }|
  150. |
  151. ]],
  152. }
  153. -- Trust database is not updated
  154. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  155. eq(nil, trust)
  156. -- Cannot write file
  157. pcall_err(command, 'write')
  158. eq(true, api.nvim_get_option_value('readonly', {}))
  159. end)
  160. end)
  161. describe('trust()', function()
  162. local xstate = 'Xstate'
  163. setup(function()
  164. clear { env = { XDG_STATE_HOME = xstate } }
  165. n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
  166. end)
  167. teardown(function()
  168. n.rmdir(xstate)
  169. end)
  170. before_each(function()
  171. t.write_file('test_file', 'test')
  172. end)
  173. after_each(function()
  174. os.remove('test_file')
  175. end)
  176. it('returns error when passing both path and bufnr', function()
  177. matches(
  178. '"path" and "bufnr" are mutually exclusive',
  179. pcall_err(exec_lua, [[vim.secure.trust({action='deny', bufnr=0, path='test_file'})]])
  180. )
  181. end)
  182. it('returns error when passing neither path or bufnr', function()
  183. matches(
  184. 'one of "path" or "bufnr" is required',
  185. pcall_err(exec_lua, [[vim.secure.trust({action='deny'})]])
  186. )
  187. end)
  188. it('trust then deny then remove a file using bufnr', function()
  189. local cwd = fn.getcwd()
  190. local hash = fn.sha256(read_file('test_file'))
  191. local full_path = cwd .. pathsep .. 'test_file'
  192. command('edit test_file')
  193. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
  194. local trust = read_file(stdpath('state') .. pathsep .. 'trust')
  195. eq(string.format('%s %s', hash, full_path), vim.trim(trust))
  196. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
  197. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  198. eq(string.format('! %s', full_path), vim.trim(trust))
  199. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
  200. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  201. eq('', vim.trim(trust))
  202. end)
  203. it('deny then trust then remove a file using bufnr', function()
  204. local cwd = fn.getcwd()
  205. local hash = fn.sha256(read_file('test_file'))
  206. local full_path = cwd .. pathsep .. 'test_file'
  207. command('edit test_file')
  208. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
  209. local trust = read_file(stdpath('state') .. pathsep .. 'trust')
  210. eq(string.format('! %s', full_path), vim.trim(trust))
  211. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
  212. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  213. eq(string.format('%s %s', hash, full_path), vim.trim(trust))
  214. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
  215. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  216. eq('', vim.trim(trust))
  217. end)
  218. it('trust using bufnr then deny then remove a file using path', function()
  219. local cwd = fn.getcwd()
  220. local hash = fn.sha256(read_file('test_file'))
  221. local full_path = cwd .. pathsep .. 'test_file'
  222. command('edit test_file')
  223. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
  224. local trust = read_file(stdpath('state') .. pathsep .. 'trust')
  225. eq(string.format('%s %s', hash, full_path), vim.trim(trust))
  226. eq(
  227. { true, full_path },
  228. exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
  229. )
  230. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  231. eq(string.format('! %s', full_path), vim.trim(trust))
  232. eq(
  233. { true, full_path },
  234. exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
  235. )
  236. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  237. eq('', vim.trim(trust))
  238. end)
  239. it('deny then trust then remove a file using bufnr', function()
  240. local cwd = fn.getcwd()
  241. local hash = fn.sha256(read_file('test_file'))
  242. local full_path = cwd .. pathsep .. 'test_file'
  243. command('edit test_file')
  244. eq(
  245. { true, full_path },
  246. exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
  247. )
  248. local trust = read_file(stdpath('state') .. pathsep .. 'trust')
  249. eq(string.format('! %s', full_path), vim.trim(trust))
  250. eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
  251. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  252. eq(string.format('%s %s', hash, full_path), vim.trim(trust))
  253. eq(
  254. { true, full_path },
  255. exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
  256. )
  257. trust = read_file(stdpath('state') .. pathsep .. 'trust')
  258. eq('', vim.trim(trust))
  259. end)
  260. it('trust returns error when buffer not associated to file', function()
  261. command('new')
  262. eq(
  263. { false, 'buffer is not associated with a file' },
  264. exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])
  265. )
  266. end)
  267. end)
  268. end)