security: Improve trust model with plugin authors by controlling executed code
Currently vim-plug doesn't appear to have a well supported means of controlling what source code is included+executed when vim starts up since the latest content is pulled in by default.
I think we should implement lockfile system for the following reasons:
- Reproducible environments across machines
- Prevention of unexpected plugin updates
- Easier rollbacks to known-good states
The current snapshot feature, while useful, has limitations:
- Slow startup times due to executing multiple git commands on each Vim launch
- Doesn't prevent automatic updates during normal plugin operations
A lockfile approach would:
- Store plugin commit hashes in a simple, fast-to-read format
- Be checked during updates to determine if changes are needed
- Only update plugins when explicitly requested or when the lockfile changes
- Significantly reduce startup overhead compared to the current snapshot system
This feature would enhance vim-plug's utility for users prioritizing stability, reproducibility, and performance in their Vim/Neovim setups.
- Type:
- [ ] Bug
- [ ] Enhancement
- [x] Feature Request
- [ ] Question
- OS:
- [x] All/Other
- Vim:
- [x] Terminal Vim
- [x] GVim
- [x] Neovim
note: I know https://github.com/junegunn/vim-plug/issues/954 was opened previously, this is effectively restarting that convo. The threat of a supply chain attack on vim plugins isn't impossible and I think we can make this project more secure pretty easily.
It would also be quite helpful to register programs to call on plugin updates when they do occur, so users can have an opportunity to perform additional security validation of new code arriving.
I want to surface this again and reframed it slightly as a security related concern (but it has user experience benefits too).
- Slow startup times due to executing multiple git commands on each Vim launch
- Doesn't prevent automatic updates during normal plugin operations
I think there is some misunderstanding. When you run :PlugSnapshot, you are effectively creating a lock file. Once the commit hashes are extracted, there's no need to run any git commands, so it shouldn't affect the startup time, and vim-plug will not update the plugins with hash values specified.
Here's an example.
- Say you have this vimrc file:
call plug#begin()
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'
Plug 'junegunn/seoul256.vim'
call plug#end()
- You run
:PlugInstallto install the plugins - Then you run
:PlugSnapshotto extract the hashes.
" Generated by vim-plug
" Sat Mar 1 10:50:21 2025
" :source this file in vim to restore the snapshot
" or execute: vim -S snapshot.vim
silent! let g:plugs['fzf'].commit = '3ba82b6d87348b119f9a7fd168ad8a597a18b4b2'
silent! let g:plugs['fzf.vim'].commit = '6cda389bdea953c9c66a3cfe57e40463ffd61ae9'
silent! let g:plugs['seoul256.vim'].commit = 'b21c9e63f7c2d543db8b34a393a0b42ec7e9b891'
PlugUpdate!
- You copy three lines and put it before
plug#end()
call plug#begin()
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'
Plug 'junegunn/seoul256.vim'
silent! let g:plugs['fzf'].commit = '3ba82b6d87348b119f9a7fd168ad8a597a18b4b2'
silent! let g:plugs['fzf.vim'].commit = '6cda389bdea953c9c66a3cfe57e40463ffd61ae9'
silent! let g:plugs['seoul256.vim'].commit = 'b21c9e63f7c2d543db8b34a393a0b42ec7e9b891'
call plug#end()
- Now you have a set of plugins that are locked to the specified revisions. The extra lines don't really affect the startup time.
- If you do want to update a plugin, either edit the commit hash, or comment out the line so that vim-plug chooses the latest revision.
The process is a little cumbersome, but the functionality is there. Maybe the user can write a custom script to automate/simplify the process, but I guess it would be nice if vim-plug could help in some way.