How to stay safe when installing Obsidian plugins
Plugins in Obsidian are if not the main, then one of the main killer features that make the tool truly universal. The ability to customize the app so flexibly, especially on mobile, is probably unmatched by any other note-taking app. And I'm personally deeply grateful to the Obsidian developers for not restricting the API and giving community plugins the same capabilities as themselves, essentially creating fair competition between their commercial solutions (Sync, Publish) and third-party ones.
However, with great flexibility we always have to accept certain trade-offs. Security being one of them. So everyone using plugins should understand what they're paying for these capabilities and how they can reduce their risks.
Threat model
First, we need to understand what exactly an attacker can do through a compromised plugin. The plugin API currently allows running any code without execution context restrictions. This means plugins can:
- make network requests to any website
- download and upload files
- work with the file system (not just the vault, but the entire file system)
- launch other processes
So plugins can contain malware like cryptominers and ransomware, among other things.
It's also important to understand how plugins reach us. A third-party developer uploads the plugin source code to GitHub, then requests a review from the Obsidian developers. They check the source code and if everything's fine, publish it to the plugin directory. The developer can then update the plugin by uploading new versions, but as far as I know, these no longer go through review by the Obsidian team (correct me if I'm wrong). The process is described here: https://docs.obsidian.md/Plugins/Releasing/Submit+your+plugin
When we click the install button, what gets downloaded is not the source code but a built program, usually in the form of three files: main.js, styles.css and manifest.json. The build is usually done via GitHub Actions, which automates the release of new updates. But the developer can also upload the final files manually, so they don't necessarily match the source code you see in the repository.
So I would highlight several main ways malicious code can get onto your computer along with a plugin:
- A malicious developer wants to release a harmful plugin. They publish some useful plugin that initially passes review. Then in a subsequent update they publish a built plugin with malicious code (most likely without updating the source code) and you receive it with the new update.
- The account (GitHub or
npm) of a legitimate plugin developer you're using gets hacked and an update with malicious code is published in their name. Such hacks unfortunately happen quite often. - The account of a developer of one of the
npmpackages used in one of your plugins gets hacked, and automatic updates or an inattentive developer installs it and releases a plugin using the compromised code. This is exactly the risk that u/lishid recently wrote about and how the Obsidian development team avoids it: https://obsidian.md/blog/less-is-safer/. But the same risk exists for Obsidian plugins too, not just the app itself.
There are certainly other possible risks, but regarding plugins specifically, these are the most likely.
How to protect yourself
Now that we understand what risks we face, we can talk about how to stay safe.
The most obvious solution: don't install plugins. This way we avoid all risks, but as I wrote at the beginning, it would be a shame to give up all the capabilities that plugins provide.
Second option: only use the most popular, time-tested plugins. This way we get the most important functionality and eliminate the first scenario from the risks described above. Additionally, you can reduce the probability of scenarios 2 and 3 by updating less frequently, but this is also a trade-off since updates may contain important fixes, and old versions can also be compromised and installed, for example, when you sync a new device.
You can build the plugin code from source yourself. This is usually quite simple and fast. This way you can be sure that what the developer published on GitHub is what you're installing in Obsidian, not some compromised build. I'll briefly describe how to do this for Mac users. For Windows users it's almost the same, except commands need to be run in WSL and I can't describe them exactly since I don't have a Windows computer at hand. And Linux users already know all this.
So, you'll need two tools: git (usually installed with Xcode from the App Store or via brew, more details here: https://git-scm.com/downloads/mac) and docker: https://docs.docker.com/desktop/setup/install/mac-install/. And the standard terminal. Then:
- Download the plugin source code (I'll use the excellent dataview plugin as an example):
git clone https://github.com/blacksmithgu/obsidian-dataview.git
- The command above will download the source code to the
./obsidian-dataviewfolder (the folder is always named after the plugin). Navigate to it with:
cd obsidian-dataview
- Next we need to install dependencies and build the project. The easiest (and safest) way is to use a docker image with everything we need pre-installed (if you're not familiar with docker, think of it as a virtual machine that runs in your terminal where we'll execute all further commands):
docker run -it --rm -v ./:/app -w /app node:22 bash
- After running the command above, you'll be "inside the virtual machine". Now let's install the plugin dependencies - these are other programs needed for it to work. Run:
npm ci
- Now we can build the plugin by running (almost always, but there are exceptions):
npm run build
- If you don't see any error messages in the console, congratulations, you've probably built your first program. Now exit
dockerwith theexitcommand. - In the folder you just created, you should see a new file:
main.js. This is the built plugin code. It often lives not in the project root but in abuildorreleasefolder or less commonly in another similar one. Next to it or in the project root there may also bestyles.css. And in the project root there's alwaysmanifest.json. The latter is the plugin description. Among other things, it contains itsid.
- The last thing we need to do is copy the files
main.js,styles.cssandmanifest.jsonto a folder in your vault:./vault/.obsidian/plugins/obsidian-dataview(you need to create the folder yourself first). If you don't see the.obsidianfolder, enable dot-file display with the keyboard shortcutcmd + shift + .in Finder. Now reload plugins in Obsidian and you should see your new plugin.
Despite the fact that building from source code of a known plugin already does a lot for security, the only way to almost certainly protect yourself from the above risks is to review the source code. This requires understanding it, but often a quick scan of the files is enough to understand what it does. Here's what to look for:
- Network requests. Almost any malicious code needs to communicate with the network somehow. Either to upload information from the victim's computer, or conversely, to download other code that will carry the main payload. Look at where the plugin connects to. The simplest and quickest approach is to search for
http. Usually there will be many URLs from comments, thepackage-lock.jsonfile and various URLs shown in the interface (like funding and help). But you should be concerned if the plugin downloads something and then executes the received code. Look for theevalcommand, for example. - Malicious code is usually disguised somehow. Go through it and look for incomprehensible long character sequences like:
_0x9e38=['\x28\x2E\x2B\x3F.... Also check if there are any compiled binaries among the files (they won't read as text). Sometimes plugins usewasm, so this isn't always bad, but you should at least understand why they need it. - Look for system process launches. Packages like
child_process,execa,cross-spawnare usually used for this, but not exclusively. - Check
package.json. Of course, non-JS developers won't find much interesting there, but ideally you should look at what dependencies the plugin uses. You can check packages on npmjs.com which describes what functionality they provide. Pay attention to packages with few downloads or functionality that doesn't seem necessary for the plugin. There are automated checking tools, but that's for another time - this post is long enough as it is. package.jsonmay also contain scripts that sometimes perform malicious actions, but I can't give general recommendations on those since you need to look at what exactly they do.
In conclusion
Just so you know, with this post I didn't want to discourage anyone from using plugins. On the contrary, I personally consider them Obsidian's best feature and use many awesome plugins, for which I'm also very grateful to their developers. But I hope this text will give many people a better understanding of what exactly can go wrong and dispel illusions of security or conversely of particular danger of plugins. So use plugins and may they help you with your tasks. All the best!