58 comments

[ 4.7 ms ] story [ 53.2 ms ] thread
What does it do about the curl|bash itself downloading software at runtime?
That's why you need to inspect the script.
I like this. Convincing people not to pipe remote scripts to their shell seems like a lost battle, so making it safer to do is a very good mitigation strategy.
Splendid idea, especially since "curl | bash" can be detected on the server [1] (which if compromised could serve hostile content to only those who do it)

[1] https://web.archive.org/web/20250622061208/http://idontplayd...

Yes, ... but if the server is compromised, they could also just inject malware directly into the binary that it's installing, right? As I see it, at the end of the day you're only safe if you're directly downloading a package whose hash you can confirm via a separate trusted source. Anything else puts you at the mercy of the server you're downloading from.
This is one of those theoretical issues that has absolutely no practical implications.
(comment deleted)
I wonder if domain validation might be a good addition to this? You could encode a public key in a TXT record for the domain, and if present, vet could check a signature in the shell script against the key in the TXT record. It wouldn't stop attacks where the owner lost control of the DNS records, but it would stop the "webserver hijack" attack vector.
TLSA records exist, but are for the entire server rather than a single binary or script.
An option to run the potentially harmful script in a rootless container, then dump filesystem diffs, audit events, etc...might be helpful.

I get containers aren't perfect isolation, but...

Could do it in a VM too.
Reminder that the pattern has the same risk as downloading software that you haven’t audited and verified the binary matches the source.
Reminder that there is the reductive argument that basically everything you download is arbitrary code, but throwing away the code that is run seems uniquely silly.
My problem with curl|bash is not that the script might be malicious - the software I'm installing could equally be malicious. It's that it may be written incompetently, or just not with users like me in mind, and so the installation gets done in some broken, brittle, or non-standard way on my system. I'd much rather download a single binary and install it myself in the location I know it belongs in.
I've also seen really wonderfully-written scripts that, if you read them manually, allow you to change where whatever it is is installed, what features it may have, optional integration with Python environments, or other things like that.

I at least skim all the scripts I download this way before I run them. There's just all kinds of reasons to, ranging all the way from the "is this malicious" to "does this have options they're not telling me about that I want to use".

A particular example is that I really want to know if you're setting up something that integrates with my distro's package manager or just yolo'ing it somewhere into my user's file system, and if so, where.

Much of the reason `curl | bash` grew up in the Linux ecosystem is that "single binary that just runs" approach isn't really feasible (1) because the various distros themselves don't adhere to enough of a standard to support it. Windows and MacOS, being mono-vendor, have a sufficiently standardized configuration that install tooling that just layers a new application into your existing ecosystem is relatively straightforward: they're not worrying about what audio subsystem you installed, or what side of the systemd turf war your distro landed on, or which of three (four? five?) popular desktop environments you installed, or whether your `/dev` directory is fully-populated. There's one answer for the equivalent of all those questions on Mac and Win so shoving some random binary in there Just Works.

Given the jungle that is the Linux ecosystem, that bash script is doing an awful lot of compatibility verification and alternatives selection to stand up the tool on your machine. And if what you mean is "I'd rather they hand me the binary blob and I just hook it up based on a manifest they also provided..." Most people do not want to do that level of configuration, not when there are two OS ecosystems out there that Just Work. They understandably want their Linux distro to Just Work too.

(1) feasible traditionally. Projects like snap and flatpak take a page from the success Docker has had and bundle the executable with its dependencies so it no longer has to worry about what special snowflake your "home" distro is, it's carrying all the audio / system / whatever dependencies it relies upon with it. Mostly. And at the cost of having all these redundant tech stacks resident on disk and in memory and only consolidateable if two packages are children of the same parent image.

Yes! What I really want from something like this is sandboxing the install process to give me a guaranteed uninstall process.
My problem with it is that it encourages unsafe behavior.

How many times will a novice user follow that pattern until some jerk on discord drops a curl|bash and gets hits

IRC used to be a battlefield for these kinds of tricks and we have legit projects like homebrew training users it’s normal to raw dog arbitrary code direcly into your environment

This is always the beef that I've had with it. Particularly the lack of automatic updates and enforced immutable monotonic public version history. It leads to each program implementing its own non-standard self-updating logic instead of just relying on the system package managers. https://docs.sweeting.me/s/against-curl-sh
This exactly. You never know what it will do. Will it simply check that you have Python and virtualenv and install everything into a single directory? Or will it hijack your system by adding trusted remote software repositories? Will it create new users? Open network ports? Install an old version of Java it needs? Replace system binaries for “better” ones? Install Docker?

Operating systems already have standard ways of distributing software to end users. Use it! Sure maybe it takes you a little extra time to do a one off task of adding the ability to build Debian packages, RPM, etc. but at least your software will coexist nicely with everything else. Or if your software is such a prima-donna that it needs its own OS image, package it in a Docker container. But really, just stop trying to reinvent the wheel (literally).

Many times a day both in scripts and interactively I use a small program I refer to as "yy030" that filters URLs from stdin. It's a bit like "urlview" but uses less complicated regex and is faster. There is no third party software I use that is distributed via "curl|bash" and in practice I do not use curl or bash, however if I did I might use yy030 to extract any URLs from install.sh something like this

    curl https://example.com/install.sh|yy030
or

    curl https://example.com/install.sh > install.sh
    yy030 < install.sh
Another filter, "yy073", turns a list of URLs into a simple web page. For example,

    curl https://example.com/install.sh|yy030|yy073 > 1.htm
I can then open 1.htm in an HTML reader and select any file for download or processing by any program according to any file associations I choose, somewhat like "urlview".

I do not use "fzf" or anything like that. yy030 and yy073 are small static binaries under 50k that compile in about 1 second.

I also have a tiny script that downloads a URL received on stdin. For example, to download the third URL from install.sh to 1.tgz

     yy030 < install.sh|sed -n 3p|ftp0 1.tgz
"ftp" means the client is tnftp

"0" means stdin

Nice. Next step: provide an interactive shell (plugin) that detects curl | (ba)sh and suggests running vet instead.
You can also use vipe from moreutils:

  curl -sSL https://example.com/install.sh | vipe | sh
This will open the output of the curl command in your editor and let you review and modify it before passing it on to the shell. If it seems shady, clear the text.

vet looks safer. (Edit: It has the diff feature and defaults to not running the script. However, it also doesn't display a new script for review by default.) The advantage of vipe is that you probably have moreutils available in your system's package repositories or already installed.

Am I missing something? Even if you do `vet foobar-downloader.sh` instead of `curl foobar-downloader.sh | bash`, isn't your next command going to be to execute `foobar` regardless, "blindly trusting" that all the source in the `foobar` repository isn't compromised, etc?
It's crazy that so much ink is spilled on curl | bash, but then those same people will happily run the 50MB binary it downloads for you without a second thought. Someone explain this to me, please.

Let's consider rust: https://www.rust-lang.org/tools/install

Specifically, consider these two files:

A. a shell script, written by the Rust core developers, hosted on the Rust official website behind TLS

B. a compiler binary, written by the Rust core developers, hosted on the Rust official website behind TLS

Why is everyone so afraid of A, but not afraid of B?

I was hoping this would have a curl | bash installer. Was not disappointed!
The whole point of "curl|bash" is to skip dependency on package managers and install on a barebone machine. Installing a tool that allow to install tools without installation tool is...
we've been curl | bashing software on windows since forever, it was called 'downloading and running an installer' and yes, there was the occasional malware. the solution to that was antivirus software. at this point even the younger hners should see how the wheel of history turns.

meanwhile, everyone everywhere is npm installing and docker running without second thoughts.

Tired of pointless "security" nonsense. This is silly.
curl github.com/vet-run/install.sh | bash
Given the conversations in this thread about the annoying package management that leads to so much use of curl | bash, I have a question: Which Linux distro is the least annoying in this regard? Specifically, I mean 1) packages are installed in a predictable location (not one of 3-5 legacy locations, or split between directories); 2) configuration files are installed in a predictable location; 3) Packages are up to date; 4) There is a a large selection of software in the repositories; 5) Security is a priority for the distro maintainers; 6) It's not like pulling teeth if I want/need to customize my setup away from the defaults.

I have always used Debian / Ubuntu because I started with my server using them and have wanted to keep the same tech stack between server and desktop - and they have a large repository ecosystem. But the fragmentation and often times byzantine layout is really starting to grind my gears. I sometimes find a couple overlapping packages installed, and it requires research and testing to figure out which one has priority (mainly networking...).

Certainly, there is no perfect answer. I am just trying to discover which ones come close.

Can’t recall the last time I used `curl … | bash` to install anything on personal or remote devices.

Switched to nix + home-manager as a package manager to replace defacto package managers on some operating systems (ie, darwin uses macports or homebrew).

In cases where the package isn’t available in nixpkgs, can create my own derivation and build it from source.

If I am super paranoid, spin up sandboxed vm with minimal nixos. Use nixos-anywhere to setup vm. Install/build suspicious package. Then do reconnaissance. Nuke the vm after I am done.

Nix, like any other software, isn’t fool proof. Something is likely to get through. In that case, identify the malicious package in nix store. Update your flake to remove/patch software that introduced it. Then nuke the system completely.

Then rebuild system using your declarative system configuration without malicious software.

Is nix for everyone? God no, there’s a massive learning curve. But I will say that once you get past this learning curve, you will never need to install anything with this pattern.

Had there been a single notable incident of curlbash leading to a malware outbreak that this would have prevented?
Funny, I had this need just today, but with a not-so-popular GitHub repo I cloned today. Before running it, I opened the folder in Cursor and requested a check for suspicious activities, which after a good scan of README and source files, Cursor reported back that it was ok to proceed.

I think getting an (optional?) AI heads-up before reviewing it myself would be great for cURL shell scripts as well. I'm prone to not seeing dark patterns in editor, and tools like vet could as well be tricked into not seeing the dark pattern, malicious intent, or just hazardous code lurking.

The solution to executing untrusted code is not to execute more untrusted code, especially through a tool which has not itself been "vetted".