Skip to content

Modelines cause too many issues#19875

Closed
chrisbra wants to merge 1 commit intovim:masterfrom
chrisbra:modeline
Closed

Modelines cause too many issues#19875
chrisbra wants to merge 1 commit intovim:masterfrom
chrisbra:modeline

Conversation

@chrisbra
Copy link
Copy Markdown
Member

Problem: Modelines cause too many issues
Solution: Disable modeline by default

Note: this is a slightly backwards incompatible change.

@koron
Copy link
Copy Markdown
Contributor

koron commented Apr 1, 2026

After this change, many Vim users, including myself, will probably add set modeline to their .vimrc file. If that happens, it becomes unclear whether this can still be considered a security measure.

As an alternative, I propose changing the vim so that all options are initially marked as incompatible with modeline, and then clearly safe options are re-marked as compatible with modeline one by one. Currently, we use a blacklist approach to specify options that cannot be used with modeline, but going forward, we will use a whitelist approach to specify options that can be used with modeline.

I think it's acceptable for all options to be temporarily unavailable in modeline during that process. Alternatively, the initial change could involve registering only the options used in modeline in the vim source code to the whitelist.

@bennyyip
Copy link
Copy Markdown
Contributor

bennyyip commented Apr 1, 2026

What exactly is "too many issues"? I know there is a recent modeline security bug(GHSA-2gmj-rpqf-pxvh). Is there anything else?

I agree with the whitelist approach. Here is a list of common options that should be safe:

autoindent
colorcolumn
commentstring
conceallevel
expandtab
fileencoding
filetype
foldenable
foldlevel
foldmarker
foldmethod
modifiable
readonly
rightleft
shiftwidth
softtabstop
tabstop
varsofttabstop

@BrianInglis
Copy link
Copy Markdown

A lot of programmers use various editor (eclipse, emacs, gedit, Kate, VScode, Zed) modelines where supported, as many text files have syntax not recognized as unique MIME types, suffixes, by vim, or maybe also language scripts which need alternate writing directions, especially for comments?
Security should be enhanced for those, but any and all changes should be documented thoroughly and preannounced as deprecated, before dis-/enabling the new features in succeeding release(s).
Perhaps some new approach(es) should also be supported, like other editors' modelines for compatibility, or EditorConfig features, but including support in command line versions, where to my mind modelines supported features previously commonly available only with GUIs.

@jamessan
Copy link
Copy Markdown
Contributor

jamessan commented Apr 1, 2026

FWIW, Debian Vim packages have defaulted to 'nomodeline' for 20 years, and also recommended vim-securemodelines as an way to allow list modelines (with an opinionated builtin list).

@chrisbra
Copy link
Copy Markdown
Member Author

chrisbra commented Apr 2, 2026

It started with this blog report from calif.io, which resulted in CVE-2026-34714. The written report was extremely hard to read due to the verbose amount of text and was clearly just a dump from claude code. I do expect much better reports from professional security researchers.

This apparently triggered repeated attempts from others to find similar issues, which resulted in CVE-2026-34982. And even more LLMs joined the game and flooded me with additional security reports of dubious quality. Most of them where actual bugs but did not classify as security issue (at least according to my opinion) and that was the reason for the many additional commits which did not go through PR/CI here and that is also the reason why I seemed not that active the last few days.

You can guess how much fun I had, since this happened during my week off so I can take care of my son for easter vacation. This is the reason for commit 2c976d0 to clarify on how to report security issues here.

In any case, those 2 CVEs above triggered the people from oss-sec to question the use of enabled modelines by default and I must say I agree. However, I guess a separate whitelist also makes sense. I guess we should have an option like 'modelinewhitelist', which when set/enabled (which it should by default), should only allow such a list and does therefore restrict the number of options that can be set (when 'modeline' is enabled).

So I guess this makes sense?

@lilydjwg
Copy link
Copy Markdown
Contributor

lilydjwg commented Apr 2, 2026

I like the whitelist approach, but I have doubt about making it configurable: say there is an option X that does a simple thing and the user decides it's safe to whitelist; what if later version of Vim makes X much more powerful that it is no longer safe to allow unstrusted file to set it?

@mattn
Copy link
Copy Markdown
Member

mattn commented Apr 2, 2026

I prototyped a VSCode-like trust mechanism (trustdir) to address this issue, implemented in C: #19876. The whitelist approach mentioned here also seems reasonable to me.

That said, I believe something like trustdir (a per-directory trust decision) is still necessary regardless of the approach. I implemented it in C, but thinking about making this achievable via a Vim plugin, it might be worth considering a built-in modeline() function that returns the parsed modeline values. This would allow plugin authors to implement their own trust/whitelist logic on top of it without needing changes to Vim's core modeline processing.

@vim-ml
Copy link
Copy Markdown

vim-ml commented Apr 2, 2026 via email

@chrisbra
Copy link
Copy Markdown
Member Author

chrisbra commented Apr 2, 2026

okay, latest commit adds the 'modelinestrict' option (default: on) for whitelisting only some options

@DemiMarie
Copy link
Copy Markdown

DemiMarie commented Apr 2, 2026

Please default to nomodeline. Modelines are just too risky for now.

@h-east
Copy link
Copy Markdown
Member

h-east commented Apr 3, 2026

You can guess how much fun I had, since this happened during my week off so I can take care of my son for easter vacation.

In such situations, I think it's perfectly fine to ask other Vim members for help. At the very least, I'm usually available to step in. Please prioritize spending time with your family 👍

@chrisbra
Copy link
Copy Markdown
Member Author

chrisbra commented Apr 3, 2026

Please default to nomodeline. Modelines are just too risky for now.

I think it is fine, the proposed change allows only a tiny subset of modelines by default:

'autoindent'
'cindent'
'commentstring'
'expandtab'
'filetype'
'foldcolumn'
'foldenable'
'foldmethod'
'modifiable'
'readonly'
'rightleft'
'shiftwidth'
'smartindent'
'softtabstop'
'spell'
'spelllang'
'tabstop'
'textwidth'
'varsofttabstop'
'vartabstop'

That are mostly number or boolean options for specifying indentation settings (*indent, shiftwidth, *stop, expandtab settings). Then there is a subset for folding, plus modifiable/readonly/rightleft settings which may differ per file.

The only string like options are filetype , commentstring, foldmethod and spelllang.

Most of those correspond to those of the mentioned securemodeline plugin recommended by the Debian maintainer.

@DemiMarie
Copy link
Copy Markdown

Most of those correspond to those of the mentioned securemodeline plugin recommended by the Debian maintainer.

Are there any that don’t?

If the code doesn’t do it already (I haven’t checked), would it make sense to validate the string-like options? For instance, setting filetype to something that isn’t an identifier doesn’t make sense IIUC.

@chrisbra
Copy link
Copy Markdown
Member Author

chrisbra commented Apr 9, 2026

Are there any that don’t?

vartabstop and varsofttabstop which seem to be forgotten from the plugin, commentstring which is useful for setting a custom comment sign, e.g. recommended for vim-commentary, foldcolumn to have a visual indicator for the foldlevel and foldenable to enable/disable the folding altogether, modifiable to allow disabling modifying a file.

For setting filetype we must allow composed filetypes, like html.j2 to allow combined filetypes, I don't see how we can restrict this.

Problem:  Cannot whitelist modeline options
Solution: Add the modelinestrict option

This allows to set the following options only:

  'autoindent'
  'cindent'
  'commentstring'
  'expandtab'
  'filetype'
  'foldcolumn'
  'foldenable'
  'foldmethod'
  'modifiable'
  'readonly'
  'rightleft'
  'shiftwidth'
  'smartindent'
  'softtabstop'
  'spell'
  'spelllang'
  'tabstop'
  'textwidth'
  'varsofttabstop'
  'vartabstop'

Other options won't be set but will not cause any errors.

Supported by AI

Signed-off-by: Christian Brabandt <cb@256bit.org>
@chrisbra
Copy link
Copy Markdown
Member Author

this should be ready now. Anybody has any comments?

@bennyyip
Copy link
Copy Markdown
Contributor

There are some options used in the modelines of the vim repo that is not included in the whitelist. I think they are safe to include.

fileformat
formatoptions
foldlevel
keymap

@chrisbra
Copy link
Copy Markdown
Member Author

out of those, fileformat may make sense to whitelist, but I discarded that one because I think mac and dos filetypes are largely irrelevant nowadays. For the others I'd say they probably shouldn't be set from a modeline at all and do not make sense to be set on a per file base.

@BrianInglis
Copy link
Copy Markdown

fileformat may make sense to whitelist, but I discarded that one because I think mac and dos filetypes are largely irrelevant nowadays.

Unfortunately there are still sites, including government and healthcare, that still run MS IIS web server, some MS Windows apps, that generate files with embedded \r, and vim filetypes that cause files to be/detected as CR/LF format, where appending a modeline could be a potential solution?
As could stripping the annoying terminators! ;^>

@chrisbra
Copy link
Copy Markdown
Member Author

I don't follow. If a file has dos line-endings, Vim will already detect this and re-use the existing detect fileformat. You only need to make sure to write the file initially with the correct fileformat. So in other words, you shouldn't need the modeline for the fileformat option? The only situation where this could be needed is when you actually have mixed line-endings where it is not possible to figure this out automatically. But this sounds like a really niche use-case.

@mattn
Copy link
Copy Markdown
Member

mattn commented Apr 12, 2026

fileformat is NOT an option to declare what format the file is in. It is the option that controls the line ending format used when writing the file. When a file is read, Vim automatically detects the line ending format based on fileformats and sets fileformat accordingly. So setting fileformat via modeline effectively means changing the file's line endings on the next write — it should not be whitelisted.

@mattn
Copy link
Copy Markdown
Member

mattn commented Apr 12, 2026

To clarify further: changing fileformat marks the buffer as modified (you will see + in the status line), which confirms that it is a write-affecting option, not a read-only declaration.

@BrianInglis
Copy link
Copy Markdown

To clarify further: changing fileformat marks the buffer as modified (you will see + in the status line), which confirms that it is a write-affecting option, not a read-only declaration.

As expected in ftpplugin/mail.vim:

" .eml files are universally formatted with DOS line-endings, per RFC5322.
" If the file was not DOS the it will be marked as changed, which is probably
" a good thing.
if expand('%:e') ==? 'eml'
  let b:undo_ftplugin ..= " fileformat=" .. &fileformat
  setlocal fileformat=dos
endif

I guess I should perhaps just create these emails with another filetype suffix such as .email or .mail to avoid this issue?

@mattn
Copy link
Copy Markdown
Member

mattn commented Apr 13, 2026

This currently only applies to .eml files. If you want the same behavior for other extensions, the right approach would be to propose a change to ftplugin/mail.vim, or write your own in your personal configuration. Whitelisting fileformat in modeline is not the right approach for this.

That said, I think the current ftplugin/mail.vim could be more user-friendly — it silently changes fileformat to dos, which can be confusing. It should display a warning message when the file's original line endings are not DOS.

@chrisbra chrisbra closed this in 4c28794 Apr 14, 2026
@chdiza
Copy link
Copy Markdown

chdiza commented Apr 14, 2026

Surely foldmarker should be allowed, right?

@chdiza
Copy link
Copy Markdown

chdiza commented Apr 14, 2026

I'm sorry, but this change seems like too much. Look at all these that are disallowed. I don't even do anything fancy!

foldmarker
nowrap
fenc
linebreak
listchars
syntax
scrolloff
columns
lines
showbreak
nonumber
noruler
laststatus
list

Of these, perhaps wrap, syntax, and nonumber are the strangest.

This is going to cause a lot of surprise for people.

And I'm failing to see the big benefit. Tons will just do set nomodelinestrict, which is now what I have to do, and besides: don't the issues in the CVEs have to be fixed anyway?

@chrisbra
Copy link
Copy Markdown
Member Author

Yes, and those CVEs have already been fixed. But the thing is, the amount of CVEs have shown that there is still a too large attack vector which the previous blacklist approach was not sufficient to handle and I want to make sure we protect people from this. Security people have actually insisted to disable modelines globally.

I am not sure why you would want to set all those options via a modeline, I would guess most of those options should be set globally, wrap itsself can be a bit dangerous, see 9d5208a, columns and lines do not make any sense to set via a modeline and most likely break rendering anyways, fenc again does not make sense, because by the time Vim has read the file and your modeline, it has already determined the encoding, so setting this via a modeline is too late anyhow. Most of the others are display options, that could be set via an autocommand if you really need this on a per file basis.

@benknoble
Copy link
Copy Markdown
Contributor

I don't have any real commentary on this particular change, but I will say that it might be easier to swallow upcoming behavioral changes if there was a curated place to look for what might affect a user. For example, VimLog was quite nice when it was maintained. I would consider splitting by change type (behavioral, new feature, bugfix) and even consider splitting by expected user (plugin author v. "regular" user) so folks could easily identify recent changes they care about.

Of course, I may care more because I tend to run close to HEAD; folks that only update through stable distributions or only on point releases (9.0, 9.1, etc.) may care less. I expect they'll still want a summary of significant behavioral changes though, but they can probably use :help version9, :help version-9.1, etc. Maybe to satisfy my own needs, maintaining :help incompatible-unreleased between versions would help?

OTOH, I've just learned that my 9.2.338 build has :help version-9.3, so maybe I'm all set and all this is just rambling.

Anyway, my time is limited, and I know others' is as well. Please don't read me as asking for more work from any of you all that already do so much for Vim ;) but if someone is interested in contributing in some way, I think this would be a nice addition.

@chrisbra
Copy link
Copy Markdown
Member Author

OTOH, I've just learned that my 9.2.338 build has :help version-9.3, so maybe I'm all set and all this is just rambling.

Yes, I try to document noteworthy changes as I merge them down. So version9.txt should be always recently up to date with recent changes.

@chdiza
Copy link
Copy Markdown

chdiza commented Apr 15, 2026

I am not sure why you would want to set all those options via a modeline

To ward off a possible misconception, I don't set all of those that I mentioned in the same file!

I went hunting for all the options I have ever set in a modeline, and compiled a list. Usually it's just one or two in a given modeline.

columns and lines do not make any sense to set via a modeline

They make perfect sense to set via a modeline, especially when one is using gVim. Some files I always want displayed in a larger than 80x24 viewport. I have never had a single rendering problem from setting those in a modeline in twenty years, except when I switched to kitty (which doesn't change it's size in response to those options); so now I only open the files in question in gVim or uxterm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.