So, the attack vector here is the following: attacker provides a malicious script in a .git directory, packaged for download. If the user unpacks the the package and merely opens a file, Emacs runs `git ls-files` which in turn executes the malicious script.
However, while I agree that this is a flaw in git, and Emacs should rightfully expect that running an "ls" command should be considered harmless, I do not agree with the stance that this does not require a reaction on the part of the Emacs maintainers: Now that you've been made aware of this unfortunate git behavior, I think some steps should be taken to not trigger it. That is, the functionality that runs `git ls-files` should be double checked (do we really need it? can we avoid the malicious side-effects? etc.)
These issues are technically classified as local code execution (AV:L), but they go against a pretty strong user expectation: that opening a file should be safe. In reality, they can be triggered through very common workflows like downloading and opening files, which makes them feel a lot closer to some remote scenarios, even if they’re not strictly RCE.
At the end of the day, regardless of how you classify them, it’s worth being aware of the risks when opening untrusted files in editors like Vim or Emacs.
That said, even being aware of that doesn’t necessarily help much in practice. When you’re using Emacs or Vim, you’re not really thinking about Git at all. You’re just opening and editing files. So it’s not obvious to most users why Git would be relevant in that context.
This is why I think editor maintainers should do more to protect their users. Even if the root cause sits elsewhere, users experience the risk at the point where they open files. From their perspective, the editor is the last line of defense, so it makes sense to add safeguards there.
Your defense-in-depth framing makes no sense. If .git/config or similar mechanisms are the attack vector, then adding more editor safeguards would be treating a symptom, as the real problem is git's trust model. The "users don't think about git when using editors" argument also proves too much. Many users also do not think about PATH, shell configs, dynamic linker, or their font renderer either, but you cannot make editors bulletproof against all transitive dependencies...
Seriously, it is actually backwards. Git is where the defense belongs, not every downstream tool that happens to invoke git. Asking editors to sandbox git's behavior is exactly as absurd as it sounds.
And BTW, "technically AV:L but feels like RCE" is your usual blog-post hype. It either is, or is not.
FWIW, I'm not thinking about git at all since I use Mercurial, and never enabled vc hooks in my emacs, which is based on 25.3.50.1, so wasn't affected by this exploit - I tested. I use git and hg only from the command-line.
My end-of-day analysis is to avoid git entirely if you can't trust its security model. ;)
Should the emacs developers also do more to secure emacs against ImageMagick exploits?
OTOH it’s really just the core that has been used so widely and so continuously for so long. This integration with git will have been scrutinized far less.
As an emacs user I frequently find myself in territory where I’m seemingly the only person in the world with my use case. In fact that’s half of the value: I can make emacs do whatever I want. Which means there’s security consistent with a bus factor of 1.
As for the Emacs thing, it feels utterly unfair to blame Emacs. The issue is 100% Git, and it’s unreasonable and undesirable for things like Emacs to try to put guard rails around parts of its functionality. Especially guard rails that may harm functionality. They were right to decline the suggested patch.
I don’t know how the sessions actually ran, but the Vim one probably started with “low-hanging fruit, let’s start by seeing if modeline has accidentally become insecure yet again”, and the emacs with “meh, don’t know anything offhand, before delving into code let’s see if… ooh look it runs Git, so can we apply the ol’ fsmonitor chestnut there?”
Yeah reading the above opening paragraph I was immediately going "oh Claude found out about modelines"
modelines are largely considered a (roundabout) equivalent to flat out eval, There's a reason plugins such as securemodelines exist:
Pretty sure a lot of people have spent lots of tokens into finding RCEs in vim and emacs, he is not the first person to do this.
git=(git -c core.hooksPath=/dev/null)
fsmonitor=$($git config core.fsmonitor)
if [[ -n $fsmonitor && $fsmonitor != true && $fsmonitor != false ]]; then
git+=(-c core.fsmonitor=false)
echo "Worrying git core.fsmonitor setting: $fsmonitor"
fiModelines were disabled by default for security reasons for a long time. It's kind of wild to me that they're enabled in some distributions, but there still isn't much restriction on what settings can be configured; I've never seen a modeline in the wild that did anything other than set `filetype`, `fileencoding`, `tabwidth`, `expandtab` (hard tabs vs spaces), and maybe `tabstop` / `softtabstop`.
Hence the securemodelines plugin
https://www.vim.org/scripts/script.php?script_id=1876
> if this is a class of bug that can be disabled via vim settings.
set nomodeline
That is, as parent mentioned, if it's not done already by your distro or OS.If you believe that then you have hardly scratched the surface of what your editor is capable of doing.
This, however, is mislabelled: it’s not remote code execution at all, only local. It would only become RCE if there was some path to remotely triggering Vim to open the attack file, or Emacs the attack repository, or if a normal way of fetching a repository automatically set up and executed the hook.
Basically the worst possible thing.
Also including the emacs one as a "found vulnerability" seems really disingenuous. It basically amounts to "emacs will call git status, and git status will call git hooks that can execute arbitrary code".
1. As the Emacs maintainers point out, it is indeed an issue with git, not emacs, and they are completely right to not address the issue.
2. It is something that has been known for decades. That is the reason hooks are never copied when doing git clone, to prevent this scenario (notice that the author uses wget instead of git clone to get around this).
Funnily enough this posts highlights both the strengths and the hazards of using AI, (1) quickly and easily finding real issues that would have taken a human a laborious audit to find (2) quickly and unthinkingly generating plausible sounding but ultimately meaningless vulnerability reports on some clout chasing mission and overwhelming open source maintainers with AI slop.
Barely, since there is little restriction as to what options modelines can set they should be largely considered equivalent to eval (if unintentionally). And generally they are which is why distros typically disable them by default.
IMHO in this day and age securemodelines should just be the default.
> tabpanel is missing P_MLE Unlike statusline and tabline, tabpanel is not marked with the P_MLE flag. This allows a modeline to inject %{...} expressions even when modelineexpr is disabled.
Edit: Upon re-reading the above I guess disabling modelineexpr is not the same as disabling modelines, and disabling modelines altogether might indeed prevent the issue.
I think people should be aware of this risk, especially when it looks like it's not getting fixed.
Disclosure: I didn't find the bugs. I helped wrote the blog post.
If you don't trust git, you can remove from your system or configure emacs not to use it. If you are worried about unsuspecting people with both git and emacs getting into trouble when downloading and interacting with untrusted malware from the internet, the correct solution is to add better safeguards in git before executing hooks. But you did not report this to the git project (where even minor research beyond Claude Code would reveal to you that this has already been discussed in the git community).
I suspect that what happened here was that (1) you asked Claude to find RCEs in Emacs (2) Claude, always eager to please, told you that it indeed has found an RCE in Emacs and conjured up a convincing report with included PoC (3) since Claude told you it had found an RCE "in Emacs", you thought "success!", didn't think critically about it and simply submitted Claude's report to the Emacs project.
Had you instead asked Claude to find RCEs in git itself and it told you about git hooks, you probably would not have turned around and submitted vulnerability reports to all tools and editors that ever call a git command.
That’s fair, but it would be pretty unusual for me to run Git commands in a directory I’m not actively working on. On the other hand, I open files from random folders all the time without really thinking about it, so that scenario feels much more realistic.
Who’s responsible for the vulnerability? Your text editor? The version control system with a useful feature that also happens to be a vulnerability if run on a malicious repository? The thing you extracted the repository with? The thing you downloaded the malicious repository with?
Windows + NTFS has a solution, sometimes called the “mark of the web”: add a Zone.Identifier alternate data stream to files. And that’s the way you could mostly fix the vulnerability: a world where curl sets that on the downloaded file, tar propagates it to all of the extracted files, and Git ignores (and warns about) config and hooks in marked files. But figuring out where the boundaries of propagation lie would be tricky and sometimes controversial, and would break some people’s workflows.
Edit: yeah pwned when clicking the big green trust button
/* vim: set showtabpanel=2 tabpanel=%{%autocmd_add([{'event'\:'SafeStateAgain','pattern'\:'*','cmd'\:'!id>/tmp/calif-vim-rce-poc','once'\:1}])%}: */Lack of accountability.
With other industries, when people aren't happy with their products, they ask for money back, they sue, they switch to the competition.
There are no EULA that assert removal of customer rights if the product is acquired.