securityneovimgithub-copilotneovim-plugin

How to make copilot not leak secret credentials (neovim)?


If you install the copilot neovim plugin following the official instructions, it is always on, also when you type -say- pass edit www.mybank.com/credentials which decrypts your GPG encrypted file and put it in /dev/shm for editing - oh, and copilot now sends its contents over the network to an A.I. that you told it was OK to use your stuff for training.

So, apart from deleting the copilot plugin and never using it again; is there a way to make sure this never happens again?

PS This is related: Can you make GitHub Copilot opt-in on a per-project basis? but that talks about VS, not neovim.


Solution

  • The way I solved this is by moving ~/.config/nvim/pack/github/start/copilot.vim to ~/.config/nvim/pack/github/opt/copilot.vim - to stop it from loading at all under normal circumstances.

    Then I added the following to the bottom of my ~/.config/nvim/init.vim:

    " Only load Copilot if COPILOT_EXTENSIONS is set and contains the file extension used.
    function! ShouldLoadCopilot()
      " Check if environment variable exists
      if empty($COPILOT_EXTENSIONS)
        return 0
      endif
      
      " Convert space-separated list of extensions into dictionary.
      let allowed_extensions = {}
      for ext in split($COPILOT_EXTENSIONS)
          let allowed_extensions[ext] = 1
      endfor
      
      " Check current file extension.
      let ext = expand('%:e')
      return get(allowed_extensions, ext, 0)
    endfunction
    
    command! LoadCopilot call LoadCopilotIfAllowed()
    
    let g:copilot_loaded = 0
    
    " Add Copilot status to statusline.
    function! CopilotStatus()
      return get(b:, 'copilot_enabled', 0) ? ' Copilot:ON' : ''
    endfunction
    
    " Construct statusline.
    set statusline=%<%f\ %h%m%r
    set statusline+=%=%{CopilotStatus()}\ \ 
    set statusline+=%-14.(%l,%c%V%)\ %P
    
    function! LoadCopilotIfAllowed()
      if !g:copilot_loaded
        if ShouldLoadCopilot()
          packadd copilot.vim
          Copilot auth
          let g:copilot_loaded = 1
        else
          echo "Copilot not loaded."
          return
        endif
      endif
    
      if ShouldLoadCopilot()
        Copilot enable
        let b:copilot_enabled = 1
      else
        Copilot disable
        let b:copilot_enabled = 0
      endif
    endfunction
    
    " Auto-check loading of Copilot on file open.
    autocmd BufRead,BufNewFile * LoadCopilot
    

    Now it is required to have an environment variable being set, namely (say)

    export COPILOT_EXTENSIONS="c h cpp hpp cxx hxx"
    

    with space separated file extensions, before the copilot plugin is even loaded. Also upon switching between files within a session, the plugin is disabled if the extension doesn't match (though the plugin isn't unloaded).

    I have great control over my environment by using cdeh, which means that environment variables are set and unset as a function of the current directory that I'm in. For example, I added export COPILOT_EXTENSIONS="c h cpp hpp cxx hxx" to /home/carlo/projects/env.source so that it is set, and only set, while I'm working on any of my C++ projects.