Capabilities-based security prevents these supply chain attacks! (Even though in this case most of the downloads were of packages including unwanted telemetry and not something more dangerous.)
“…And now if a [color theme] wants to read your data and send it to a server, it needs a filesystem capability and a network capability. It should be an obvious red flag if a [theming addon] were to ask for those dependencies. And this makes it hard to hide malware.” https://borretti.me/article/how-capabilities-work-austral
The original quote talks about a leftpad dependency but it’s a drop-in substitution to apply it here, too. It’s right there in the screenshot:
const https = require(‘http’)
const os = require(‘os’)
Both of those calls ought to error out with “Error: Network capability not provided” and “Error: filesystem capability not provided”, respectively.
Yes! Sadly, today nobody seem to care about the principle of least privileges. Take Linux as an example: every program you install gets full access to the system, and gets thousands of privileges it doesn't need. If your PDF reader is vulnerable, it will have both access to your SSH keys and to the Internet to upload them (and if you block Internet access for a PDF reader, it still can send the data by connecting to systemd DNS resolver via DBUS and exporting your keys as DNS requests).
Security is a joke in Linux in default configuration.
> . It should be an obvious red flag if a [theming addon] were to ask for those dependencies
No. Theming addons should not even be able to ask for those privileges.
> No. Theming addons should not even be able to ask for those privileges.
That's not the principle of least privilege, that's a user rule, and it isn't necessarily a good one.
I can imagine, for example, a theming add-on which queries a weather API and picks colors based on that, perhaps displaying a nice weather bar in the status line.
Such a theme would need to be granted this privilege, which should ideally be restricted to a hosts list, such that the user could pick another weather endpoint, but the theme can't promise weather and give weather and Google Analytics or your choice of telemetry endpoint.
> Take Linux as an example: every program you install gets full access to the system...
... which should be locked down by group assignments and file-system permission flags. What the hell am I missing? The POSIX model has worked extraordinarily well for decades. The issue you're describing would be no different in Windows or any other operating system. If you install a malicious program, it can embed whatever protocols and communication channels it needs to exfiltrate any data your user account has access to. It's great to advocate for absolute least privilege in programs, but the only people who want to manage a matrix of permissions for every application the system would be IT managers who don't have to deal with the hassle or the complaints. This is precisely why so many things slip through on mobile. "Ain't nobody got time for that."
Do you execute your SSH agent as a different user/group from the one you use for your PDF reader? Does Firefox only get to read and write to ~/.config, ~/.cache and ~/Downloads?
The capabilities are there for the people who want to hot glue some elaborate contraptions together, but there is no good UX or DX for doing this in a composable manner for end user consumption.
A combination of very restrictive globals.local and <appname>.local files added to Firejail + custom apparmor rules allows me to jail applications as well or likely better than is possible on any other platform. Other tools are available that accomplish the same, if either or both of these is not to your liking (firejail has improved greatly with recent versions, if your opinion was formed years ago, but not all default profiles have migrated to restrictive explicit allow policies vs. permissive explicit deny policies yet, and those old policies are a pita to add your own restrictions to).
You could also just live with the default rule sets Firejail and Apparmor ship with, and have less restrictively jailed apps by default, but in many cases sufficiently jailed to prevent access to e.g., your ssh-agent without any additional effort-- in this case jailing is just install firejail+apparmor and create a few symlinks for the applications you want to be jailed (IMO still not a high effort bar; and, there is a single command that will create symlinks for you, for everything firejail ships a default profile for, if you feel comfortable running that).
Nothing that interacts with the Internet or untrusted files has access to anything confidential in my home dir, or anywhere else on my system unless that access is needed (including the named pipe for ssh-agent). None of these applications have network access that don't need it. Apps can only use syscalls that are explicitly listed, cannot gain capabilities beyond the restricted capabilities listed, only have access to the bins necessary to run, can only see existence of processes in their own jail, etc.
If, privileged filesystem or network access isn't required as the rule, I'll add a separate profile with extra privileges, and the default profile will not have that access. E.g., for pdf files, I have 'atril' and 'atril-privileged'. Neither atril profile has network access, nor access to ssh keys, global ~/.cache, etc. The day to day one can only read from a few locations on the filesystem, and can only write to two paths. The privileged one can also read where I save private info like tax information.
Firefox profiles run entirely in tmpfs, with each profile having its own ~/.cache ~/Downloads (the real ~/Downloads contains symlinks to each of the jailed Download dirs), etc. I setup the tmpfs for firefox and chromium with a wrapper script, so I can easily handle data that I want to persist and to work around limitations in Firejail. There are separate launchers (rarely used) for Firefox/chromium which allow persistently modifying the profiles (most firefox config is via user.js and misc sqlite/json files, but I'm unaware of an equivalent for chromium).
DBUS is a pita for jails, though. To prevent escaping your private mount namespace jail, you really have to kill dbus access inside the jail (which requires a private net namespace or disallowing unix domain sockets to be really sure; but sometimes all you can do is add a filter-- Firejail allows for all of these options [with limitations on net namespace support for unpriv users] ).
Another addition to my setup that made it so the above restrictions were more or less transparent is a script that runs as a daemon outside the jails and gets fed filenames and urls from another script that runs inside each jail that is symlinked as e.g., symlink name 'atril' for launching a pdf viewer from within a jail-- the outer daemon script will launch an new jail instance of atril with the file passed from e.g., the thunderbird jail by the helper script inside that jail. For URLs, the same jail instance of firefox is re-used.
Indeed, SELinux and AppArmor are the tools here. I had a lot of trouble with them when they first came out, and just left them out of the loop. I had forgotten them since moving to Mac's about 8 years ago.
I used SELinux and AppArmor at work, and AppArmor for my own stuff. I found SELinux to be pretty unpleasant, but AppArmor rulesets / overrides not so bad. Definitely agree that there is a lot of room for improvement[1], but the tools exist, and if a person cares enough, can jail apps at least as securely as on any other platform.
[1] Other warts are not having syscall groups like openBSD pledge, so you have to track down new syscalls in each new kernel version to restrict using deny policies (which are more flexible than using explicit allow policies). And, linux capabilities are a mess that really deserves a do-over. You can get root with any of, at least, 6 capabilities. And, so much stuff is crammed into CAP_SYS_ADMIN and CAP_NET_ADMIN, that you effectively lose any granularity in selectively allowing privileged activities.
You can get weaker jails, that are more likely to get in your way, on Linux and other platforms that "just work-ish" though [1].
Default jails on Linux with Firejail really is just install the application and run a single command, to jail everything it knows about. Or just create symlinks manually to be more selective. Not a high bar.
Having the ability to customize means not having to change the way I do things to conform to the whims of some random company. Jails that "just work", but do not allow customization are jailing the user too.
[1] You will need to adjust the way you work to the way the jails are setup by default. Some things you may want to do will not work at all, or not in the way you want them to. Many things will not be as extensively jailed as you might like. Applies to any of, Android, iOS, Firejail, etc., using defaults.
The MacOS app store has some sandboxing. For example, applications installed from the store can't access any file or directory unless a user has selected it in a file dialog. (The app can hold onto a ticket for later access.) I've installed Slack from the app store for this reason.
I've installed Slack on macOS using Nix. That way, the installer's sha256 is checked, and its attempts at self-modification (updating) are thwarted by /nix/store being a read-only filesystem.
I think MacOS has some protection even for manually installed apps. I downloaded iTerm2 as a .pkg and installed it manually into Applications, but the first time I typed `cd Downloads` I got an OS-level popup asking if I wanted to grant iTerm2 access to my downloads folder.
Linux has a fundamental security problem - it basically tries to protect the system from the user, not the user from himself (other user apps).
So it's difficult to modify a Linux system binary, but it's extremely easy to delete or exfiltrate a user file.
This security model might have made sense in the past, but today it's totally outdated since almost all systems, both local and in the cloud, have a single user which is the owner (has sudo).
Yeah, it's too hard to just `useradd -m name` a new user, maybe set default acl once via setfacl -m d:u:main-user:rwx /home/name for easier file sharing with the main desktop user account, and `sudo su - name` to it, and run whatever less trusted apps need to run under that user account from then on, mostly isolated from the rest of the [file]system.
Distros clearly don't allow this and none has this feature or these commands preinstalled by default, nor they are built to be multi-user OSes. :D
Fedora (and I think all the RHEL family) comes with SE Linux by default. Although I'm not that familiar with it (I tend to disable it more often than not) it seems to me like it's addressing precisely that.
But that's your choice. I have multiple "users", and only one of them has access to ssh keys, etc. Users I use for less trusted apps just have write access to their mostly empty home dir filled with some dotfiles "whatever" app created by itself.
You can firewall by process UIDs/GIDs too, and I use that to allow the user access only to the internet and not to localhost or home network, or only to localhost, etc.
I want that feature too, but in reality, many non-trivial extensions require the execution of binaries such as language servers. Applying capability models to these executables will require OS support or containerization, but the overhead for memory and disk will be huge. In fact, even an extension to auto-complete paths in .gitignore files requires running a language server written in Rust [1], and it has the real benefit of supporting multiple editors with ease. If the "prettiest java" or "python-vscode" extensions in the article insisted on needing full permissions for Java or Python execution, I believe users would be convinced and end up installing them.
> Applying capability models to these executables will require OS support or containerization, but the overhead for memory and disk will be huge.
This is because most OSes use outdated security model where the app gets all privileges by default and poor users have to build containers to revoke them, that's why there is an overhead.
If the extension only has access to project files then all applications launched by it should inherit its restrictions.
This… is a very strong objection and I think you’re right that users would be convinced. I didn’t think capabilities would be a panacea but I did think they would be pretty close, I have to revise that down somewhat.
> android tried this initially with the permissions system. But literally every app requested every permission and it became completely useless.
Google could have fixed this by allowing the user to give the app mock permissions instead, e.g. empty or randomly-generated storage, fake camera device, randomly-generated contact list, etc. Third-party solutions that allow this have been around for about a decade, but they do not have the reach that Google does.
A counter-example where a permissions system mostly still works is Mac apps. They also have to request permissions for things like using the webcam, accessing important areas of the filesystem, reading keyboard input when they’re not the active program, and so on.
It might be illustrative that Apple, who usually care a lot about good UX, made this procedure downright painful. When the app is installed it’s fine, but when it tries to use a permissioned resource for the first time that pops up a dialog box. That box is not confirm/deny, but rather sends you to the System Settings window, where you have to find the right category, find the program in that category, select Allow, and then enter your password. It seems like Apple might think the Android permissions system failed in part because they made it too easy to say yes.
I'd say VSCode is a bit different in who it's aimed at. Only because it doesn't work for a consumer product doesn't mean this wouldn't work for VSCode.
Also it might be good to be more specific. E.g. don't ask for all permissions at once, instead if the app starts talking to telemetry.endpoint.com it has to ask for these specific permissions at that point.
Then the user can see, hey this is requesting access to this particular server, that seems fishy, let's not proceed.
Are VSCode users really that much more diligent? Are you auditing the source code for every extension you install? Do you even know if the github source is the same as whats hosted on the plugins repo?
The only real solution I can see is only installing plugins from large trusted entities.
> But literally every app requested every permission
They didn't. Google regrouped and renamed the permissions until every normal thing that every application needed became grouped with rare and powerful capabilities.
Except for the ad-based crapware, almost all applications minimize their permissions.
Users here are experienced developers, so I think it's not such a big deal. In context, a theme should never need network or file storage access, so you could upfront block those for that type of extension. You can also have policies like "network access is okay but file system and network access together needs approval".
Why are you assuming most VSCode users are "experienced developers"? I would think quite the contrary, as the younger crowd is probably much more likely to be using it than more experienced developers.
I find I very quickly tire of having to think about this. You think "A theme shouldn't require file storage access" and then spend an hour looking up why it does and find out there is actually some strange but totally legitimate reason for it. And every time that happens, you lose a little bit of will to care about what permissions something requested.
There used to be a period where many android apps would explain in the description why they needed certain permissions. Those days are over.
> You think "A theme shouldn't require file storage access" and then spend an hour looking up why it does and find out there is actually some strange but totally legitimate reason for it
No. You think it is suspicious and install another theme that doesn't request anything.
Android used to ask for all permissions upfront, you have no choice. You want the app? Too bad, it is gets access to your contacts. Now apps have to ask when they need them and they are working on making file permissions more granular as well
If there was a permission dialog with boxes I would gladly check or uncheck them because nowadays I need to write bash scripts, create separate users or build containers for every third-party app. Why doesn't OS include necessary tools?
Capabilities can improve the situation significantly but we need to change how we build software too e.g. ".env" files in the project space will still be vulnerable due to the confused deputy problem.
Packj [1] flags malicious/risky NPM/PyPI/RubyGems packages by carrying out static analysis and looking for capabilities/permissions (diff from runtime permission enforcement). Supporting VSCode/browser extensions is on our roadmap.
In the context of an editor, this can be bypassed by writing this kind of code to the project, which will be run when the developer runs the project, runs tests, or in some languages even when the project is compiled.
A theme probably doesn't need access to the project files, but many extensions do. This is much harder to solve than in e.g. Android.
No, the fundamental uselessness of Deno is that it only supports process based permissions (a fact I initially debated with them over 4 years ago now…). For performance reasons all extensions run in the same process, so that wouldn’t work here.
“…And now if a [color theme] wants to read your data and send it to a server, it needs a filesystem capability and a network capability. It should be an obvious red flag if a [theming addon] were to ask for those dependencies. And this makes it hard to hide malware.” https://borretti.me/article/how-capabilities-work-austral
The original quote talks about a leftpad dependency but it’s a drop-in substitution to apply it here, too. It’s right there in the screenshot:
Both of those calls ought to error out with “Error: Network capability not provided” and “Error: filesystem capability not provided”, respectively.