Detecting the use of “curl | bash” server side (2016)
idontplaydarts.com
idontplaydarts.com
I almost always decide whether to execute someone’s else’s software based on their reputability. Is the project well known? Is it maintained, with lots of GitHub stars? My decision is never based on reading the source code. I don’t have nearly as much of a problem with curling shell scripts as the finger-wagging “actually you shouldn’t do that” crowd seem to say I should.
The one thing that really does give me the creeps is adding someone else’s apt repository to my system-wide one. I just can’t seem to square that off in my head against my more laissez-afire “well do I trust them or not?” attitude that I take for every other installation attack vector. Maybe because it means trusting the third party forever, instead of just once?
Unfortunately, it's not an easy problem to automate the detection. There are some heuristics, but you're basically writing something like Norton Antivirus for Python packages lol.
A sufficiently skilled attacker can make their code look totally innocent[0]. :)
Source: Former security engineer at Uber/Snap that's now working on tooling in this space[1].
0: "Underhanded C Competition" http://www.underhanded-c.org/
1: Open Source "Supply Chain Security" platform https://github.com/lunasec-io/lunasec
The only company that has a real chance at making a dent in the issue is GitHub and to a degree they already have.
SOURCES:
- https://www.mandiant.com/resources/blog/supply-chain-node-js
- https://www.zdnet.com/article/backdoor-found-in-ruby-library...
- https://www.reversinglabs.com/blog/mining-for-malicious-ruby...
- https://news.sophos.com/en-us/2021/10/24/node-poisoning-hija...
- https://www.bleepingcomputer.com/news/security/dev-corrupts-...
- https://portswigger.net/daily-swig/amp/malicious-python-libr...
Npm packages have really crazy dependency graphs. It's usually on the 1000s of times larger than what you get on most languages, 100s of times larger than python or ruby.
Hence left-pad. And this pet-peeve of mine https://nodejs.org/docs/latest/api/process.html#processargv (who cares about the node fullpath in argv[0]?)
The problem with left pad was a security one, not a package bloat one.
> It is highly probable that the majority of current string padding implementations are inefficient. Bringing this into the platform will improve performance of the web, and developer productivity as they no longer have to implement these common functions.
“It’s too trivial” is not why left-pad was in the news. Go read about it to understand the actual issue: https://www.theregister.com/AMP/2017/07/12/javascript_spec_s...
Of course it was useful, hence why most non-crappy languages had it in its stdlib from inception pretty much
But building a package just to do left-pad is stupid, especially since it can be implemented in a couple of lines
Nobody thinks leftPad was not a useful function. The question is, was it useful enough to counter all the risks of npm, probably not. In the stdlib there is no such risk.
My point has been this whole time that left-pad was not a story of a trivial function needlessly pulled from an external source as the person I replied to had claimed, and it appears you agree. Good!
But, with npm, suddenly it was trivial to include other packages without having to worry about sub-dependencies. The whole tree just magically added itself to your build, and only if you paid attention to the build process would you discover just how many developers you were transitively trusting.
Programs in other languages with the same kind of tooling tend to stop at hundreds or at most low-thousands of dependencies. Javascript code often reach tens or low-hundreds of thousands of dependencies.
Dependency explosion is bad all around, but JS is exceptionally bad.
https://github.com/rust-lang/docs.rs
Follow the build instructions, then you get to `cargo build` you'll see this message
Downloaded 448 crates (44.1 MB)
448 crates for a static site generator!?!?!?! WTF! react@15 — 20 deps
react@16 — 6 deps
react@17 — 4 deps
react@18 — 3 deps
The latest version of vite (a webpack replacement that's been gaining in popularity) has 14 recursive dependencies. It could be better, but it's still a significant improvement over 300+ package monstrosity you get by combining webpack with everything necessary to reimplement what vite is doing.If you pick your packages carefully (for example, looking for alternatives this one ↓ instead of the much more popular react-router), it's not as bad as it used to be.
A high level python package is more likely to depend upon 3-30 well known packages.
There is also the "Arch User Repository" which includes a bunch of useful packages that are easy to install, but with full transparency about where the contents are coming from (you can inspect the script).
They have even released an easy installed for Arch now that you can use, or you can just use Manjaro Linux. Regardless though, I really appreciate this distro for development after many years of using Ubuntu!
It's called archinstall and it's a helper script (it looks like)
The problem with piping is that bash will read line by line, keeping the connection open while it runs. If the connection fails for any reason, the script will stop, potentially breaking or corrupting things.
This can be prevented by first downloading the file, and then running it.
If the script is meant to be piped from curl, and is well written, it will be written so that it first defines everything as functions and then at the very end makes a single function call. This ensures that the script will only do anything if it has been completely downloaded.
For example, the script that rustup.rs tells you to pipe from curl is written in that way.
This is not sufficient. More care is required.
lsp_init() {
...
}
lsp_init
If the last line gets truncated between the `s` and the `p`, then `ls` gets executed. Of course `ls` is harmless, but I'm sure you can imagine how it could be worse.In other words, not only do you have to wrap your script in functions, but you have to ensure that any top-level function / command invocations are named such that they do not become different commands if truncated.
This is unsolvable in general, because the user can have any arbitrary names in their $PATH , such as custom personal utils in ~/.local/bin which can have any unforeseeable name.
It's much easier to just wrap the script in `()` to make it run in a subshell. bash will not run anything until it sees the closing `)` so truncated scripts are not a problem, and it also doesn't have the name collision problem.
For you, apparently. Other people do worry about it, which is why they do take care to wrap their script in functions. And my point is there's an even easier and more foolproof way than that.
>in the same way that a cosmic ray bitflip could cause a kernel bug that erases my entire drive but in reality I don't spend any time worrying about this.
Other people use ECC memory because they worry about this, and because it does measurably happen.
My shell[0] dies with a error "source file did not end with a newline". This is easily solvable in general, regardless of what's in PATH, as long as the shell works correctly. Valid text files do not end with bytes other than 0x0A. Being truncated at the end of a line, on the other hand, is not manifestly obviously a error.
0: That I wrote, because of bugs other than this one in bash et al, such as $FILE_WITH_SPACES; not just "my shell that I use".
Powershell will accept codesigning certs that are signed by verisign, so the workaround for an attacker who has already compromised a web site is to modify and re-sign the script with a certificate that can be obtained for $60.
Nope. Of course if someone stores a Code Signing key on the same server as the distribution server then all bets are off, but otherwise it's no possible.
PS CodeSign isn't perfect, but there is enough hoops to jump around for this not to be an easy task for a malicious actor gained access a distribution point.
Even on windows now, package are often signed by individual developers rather than an entity that you might recognise the name of.
> but there is enough hoops to jump around for this not to be an easy task for a malicious actor gained access a distribution point.
If this is an optional step (which it would have to be) then the easiest thing to do is to remove the signature from the script and modify the instructions on how to run the script. If an attacker has compromised the supply chain, unless the original host has done something incredibly dumb, chances are they're quite dedicated and jumping through a handful of extra steps arent going to stop them.
> Even on windows now, package are often signed by individual developers rather than an entity that you might recognise the name of.
This is implies what you, as an attacker:
have the access to the Enterprise PKI
can issue code signing certificates
somehow your certificate drops in the Trusted Publishers[0] on the endpoint ie you have the access or to the GPO/domain controllers (keys to the kingdom) or to the endpoint (making the whole dance with certs moot)
> If this is an optional step (which it would have to be) then the easiest thing to do is to remove the signature from the script
This would make the script to fail from running in a proper configuration
> and modify the instructions on how to run the script.
And again this requires the access to the endpoint, which makes your assumptions moot.
> If an attacker has compromised the supply chain, unless the original host has done something incredibly dumb, chances are they're quite dedicated and jumping through a handful of extra steps arent going to stop them.
Exactly, which is why you don't "signed by individual developers", don't provide the easy way to access the PKI, don't sign the scripts and yet run them with -bypass.
Come on, I did deploy PKI and PS Code Signing.
[0] https://old.reddit.com/r/PowerShell/comments/kpwi5r/powershe...
You still need to get that signature from somewhere, likely a web server. If your threat model is that you don't trust web servers but do trust the packages and repositories they give to you, then I guess this is true but that seems a little crazy given that the attacker can just change the website you're visiting to host a malicious package, and change the signature it verifies against.
> Of course, that signing key could also be compromised, but those are usually more tightly guarded than web servers,
Why is it reasonable to assume that? I don't think it is, at all. If their SSL certs are comprised, all bets are off.
> any reputable dev should have their key in a hardware enclave like yubikey or similar).
I suspect you will be very very very disappointed at the number of people who publish software that meet the criteria you've outlaid here.
Fundamentally, your argument is flawed right at the beginning because all the attacker needs to do is compromise the web server and change the installation instructions.
I have no statistics to offer, but it does seem likely to me that TLS private keys gets compromised more frequently than software/package signing keys.
Repository packages usually are signed with GPG. You can even use HTTP - it does not matter. And GPG could be used to sign packages on another machine, may be even on offline machine with HSM.
Things like pip or curl rely only on HTTPS. There are many agents between developer who built a deliverable artifact and your machine. There's WWW-server. There's some CDN with HTTPS termination. There's NSA which can issue fake certificate and MITM attack you (mostly imaginably threat for sure, but still).
And hacked WWW servers already happened. Transmission website was hacked and their binary was infected.
Now I don't claim it to be a big issue. Malevolent developer is much more dangerous and much more likely to happen. But if we want to compare those two methods - I think that repositories with proper signatures are safer.
curl -o file.sh
bash file.sh
No detectionUnless there are other sane ways to install the project, I just put in on my blacklist and ignore it.
A platform like PyPI also increases chances of something like that getting detected after it happens, giving you a chance to react in a timely way.
2020, 133 comments: https://news.ycombinator.com/item?id=25356757
2018, 146 comments: https://news.ycombinator.com/item?id=17636032
2016, 122 comments: https://news.ycombinator.com/item?id=11532599
Automatically post previous posts of the same article
It’s what I usually use to post these, but this time I was at my parents and remembered that I had seen this before, so I used the search ;)
• The sneakiness of this can be defeated with `tee` (or a variety of other ways like modified bash or a VM).
• dpkg runs arbitrary package scripts as root, so you still put trust in whoever signed the package.
• When you use `curl|sh` to install binary blob built from millions lines of code, it has countless other opportunities to include exploits with plausible deniability. If the host is hacked, they can put the payload in the binary, knowing you'll review the bash script like a hawk, and then YOLO the rest.
• Targeted attacks can can use your IP too.
• Your distro's overworked unpaid maintainer LGTMs packages with a glance, and won't review millions lines of code for backdoors.
• There is a huge gap between what people imagine they could have theoretically done properly to keep things secure and gather evidence of any potential wrongdoing, and what they actually do.
This is correct, but in those cases the maintainer is likely a much more trusted individual where more eyes are on the script as the hierarchy of maintainers sign off on things until the point it makes it into a readily accessible repository by end-users.
> Your distro's overworked unpaid maintainer LGTMs packages with a glance, and won't review millions lines of code for backdoors.
The same argument could be made about the Linux kernel itself, yet the system is surprisingly robust and examples of abuse are few and far between.
It's not about that. It's about pushing back the trust boundary to be as close to the source as possible. Of course your upstream can compromise you if they turn malicious, but having your trust boundary needlessly extend all the way out to the web server is not only unnecessary but also introduces real dangers to users (unless you also consider Transmission's incident to be one of your "Hollywood-worthy" hacks).
I'm glad people are rightfully criticizing this stupid approach. I'm glad most reputable systems use off-line signatures to verify software before running it. Security is not about absolutes. It's about thresholds.
Left aside security implications of "curl | bash" installation - what will you do if installation fails and you need to roll-back partial changes to system? How will you update this software? How will you uninstall in the future? How will you track CVEs for it, if your package manager doesn't know about its existence and all periodic scripts of your distro can not check for CVEs? How you will update libraries used by this software, are you sure this will not broke it?
Installing software via running random scripts has a ton of drawbacks to using system package manager.
A lot of the use cases of those curl | bash scripts are to support non-standard installation, like with unusual distros and user-only. And unusual distros are kind of an unsolvable thing, because people that want them won't want your package manager.
Author should not package software, distro maintainers should.
Linux package managers are missing many of the packages I want to use. The packages that they do have are often out of date.
I ship on-prem software, so I have to test on a certain set of distros using different package managers. Changing distros isn't an option for me.
> Or become packager itself.
While this would technically solve the problem, nobody wants to do this.
Instead I use Homebrew (Linuxbrew) which just works.
End of the day: the package is from a somewhat reputable source, and you don't keep life changing secrets user-accessible on your dev machine, fuck it. Also, resist installing as root. Figure out what the real permissions the thing needs are and go from there.
(if you haven't been introduced: https://dl.acm.org/doi/pdf/10.1145/358198.358210)
- Zig
- mimalloc
- libtcc
- zlib
- picohttpparser
- sqlite3
- BoringSSL
- WebKit’s JSCOnly port
- libarchive
- lol-html (+ rust)
From there, you also need clang 13, which you might also want to compile from source (though that can take an hour or more). When compiling Bun in CI, many dependencies are compiled from source (excluding Rust, LLVM, and Zig)
Every step along the way you increase the severity of the statement "If I'm fucked, then so is everyone using X". You stop when the set of people using X grows so large than you are sufficiently worthless in comparison.
Bruce Schneier already said that in 2006 [2]:
> It’s interesting: the “trusting trust” attack has actually gotten easier over time, because compilers have gotten increasingly complex
Since 2006 compilers have become even more sophisticated, but also much more complex, thus even harder to validate.
[1]: https://archive.org/details/reflections-on-trusting-trust
[2]: https://www.schneier.com/blog/archives/2006/01/countering_tr...
Also, https://www.teamten.com/lawrence/writings/coding-machines/
this would, in theory, allow you to make sure it doesn't contain any malicious code.
in reality, of course, this is rather impractical since you'd need to manually verify every single source file and every single line of code.
To be clear, "then gave up" means I ended up just running the install script. Thanks for your work on Bun! Hoping to use it for a speedy websocket server some time soon.
The first break in this bootstrap chain is mrustc, which is 11 stable versions back. Hope you've got a couple days if you need the latest stable release of rustc.
The problem with `curl | bash` isn't that the upstream author might be malicious, or have had their working copy of the repo/compiler compromised. If that's where your problem is, yeah, you're kind of stuffed.
The problem with `curl | bash` is that you're not verifying that the thing you've downloaded is the thing that the upstream author actually released, unmodified, and uncorrupted.
Checking a hash is normally sufficient to accomplish this, and isn't overly burdensome or time-consuming.
If you're particularly paranoid, you might want to check the hash against a copy you've obtained from somewhere other than the server you downloaded the release itself from. You should be able to find a separate copy of the hash from a release announcement either from the author's social media, or maybe on a mailing list archive.
(If they're not posting hashes as part of their release announcements, start badgering them to do so.)
When the callback is received, continue with malicious payload, otherwise after some timeout, send a benign script..
If I simply curl the script (without piping to bash), I'd be less suspicious if I saw a sleep than I would be if I saw a callback to a server.
Whatever executable such a script installs could itself later download + run arbitrary commands.
It was so much better than the windows way of running a random program with little visibility, and so sad when so much software changed away from that method.
In practice personally auditing the installation script for every program you're going to use and the installation script for every update is grossly impractical, for the same reason nobody reads EULAs. In the end it still boils down to trust.
Even if you are adding a third-party package repository, you just change the downloader. Although you usually get signature checking with that step for free.
And therein lies the issue: It's not the job of the software developers to provide packages for your distribution, but the job of your distribution maintainers.
So, if your distribution will probably not backport $newver of some tool to your release, you are only left with installing it via different means.
If you find yourself always installing software like this because your package repositories don't contain what you want, it may be a good idea to just check out different distros.
That's a very different scenario from having to download the dependencies as well.
The reason it's a "very linux problem" is exactly because this is a sane thing to do in a pool of insane systems.
There's absolutely no reason to ship your 1k executable with 1Gb of libraries, used by 10 other programs.
Sure something bad can still do things, but it tends not to splat files everywhere with no trace.
Some are so elaborate it's hard to poke through what they're actually doing, but a lot of them aren't.
Making an all-in-one install script that doesn't require any arguments involves making a lot of decisions for the user that you may not particularly like. Pre-reading gives a chance to decide whether or not you like those decisions.
Spend minimal resources and compromise 80% of users.
Spend an extraordinary amount of resources and compromise 99% of users. Of note is that those extra 19% of users are more security conscious and will likely detect and purge the exploit immediately.
Most of these bash scripts install open source software so I would simply recompile that software with my malware included.
Also people talk to each other. I would want to hide my malware very well so that nobody noticed and raised the alarm for as long as possible.
bash < <(curl -fsSL example.com/foo.sh)Adding maintenance overhead to a FOSS project to support a package manager is one thing, adding support for every Flavor Of The Week package manager after that initial time investment is tougher, especially when the first one is no longer en vogue.
tl;dr : the thousands of ways to package data for NIX creates a situation in which hurts maintainability unless the package maintainer lucks into picking the one that their crowd wants for any length of time. Piping data from curl works just about anywhere, even if it's a huge security faux-pas waiting to happen.
semi-unrelated aside : it strikes me as humorous that people on that side of OS aisle have cared so much about pipes being a security issue for years and years, whereas on the MS side of things people still distribute (sometimes unsigned) binaries all over the place, from all over the place, by any random mary/joe. (not to say that that's not the case on the nix side, but it feels more commonplace in MS land, that's for sure.)
Point is, somebody made something better than this little install shell script. I'll accept pip, I'm not picky.
There is almost surely no reason for $thing to be writing to my system directories. Nobody should be coaching this, it can go wrong in every way.
Binaries and libraries can come from my home directory. You won't find /home mounted with noexec outside of strict compliance environments.
Build services like OBS and COPR make the actual equipment investment of building packages basically non-existent. Roaming repositories for any distribution you could want.
Leaving the one-time cost of writing out the specs... and I suppose maintaining dependency creep.
That maintenance isn't that expensive because you'd be maintaining them in the script anyway. You're just using common domain language
Do these things and you cover 95% of the DSL:
- PKGBUILD (basically the script, AUR means you'll get maintainers)
- RPM
- DEB
Say a fourth significant option comes around, I'll guarantee you the concepts are similar enough.Macro creep is real, but this is the cost of maintenance work. Give us something to maintain.
Signed,
- A person maintaining several packages for projects with no upstream involvementThey're signed the same way as your first party packages.
If you trust the developer/maintainer, you can trust these services. It's literally the same infrastructure as OpenSUSE/Fedora/Red Hat.
As a developer you don't have to provide the infrastructure or equipment, simply whatever is to be built.
I'm not suggesting people provide their software by pure RPM or DEB files. The repositories do the important part of actually distributing the software.
If you're on either OBS or COPR you're on the fast path to having the OS maintainers do the work for you
This was the main thing I’m reacting to: installing from something like pip is usually running a ton of unvetted code downloaded from the internet. If you trust such package managers, you might as well curl to a shell.
I'll take package managers over shell scripts in concept for one main reason: they reduce reinvention.
The supply chain is always of concern, of course.
A shell script benefits from coreutils -- cp, mv, things like that. You're on your own for everything else, I don't trust that.
They themselves are untrusted code -- for all we know there's no VCS behind it at all. A package manager at least offers some guardrails!
With packages on OBS/COPR, you can at least know/verify the sources you're installing were built in a clean (offline) environment from the upstream sources. It's a small, but notable, improvement.
Also consider you need to rebuild your system and you'd like it to look the same after.
Will you find it easier to run 'pip freeze' / 'dnf history userinstalled'... or crawl your shell history for curl | bash and resolve any drift?
But there's nothing trusted about them is the point, you can ship a deb or rpm with all sorts of scripts running at installation, this is no safer than curl | sh.
If anything it's worse, when you "curl | sh" and it requests sudo you can go "mmm no we're not doing this I will happily risk compromising all my user data but it stops at my system integrity".
rpm or deb you're already running as root.
> If you trust the developer/maintainer, you can trust these services.
And you can also trust their site which you're curl-ing from.
I'm assuming some adherence to these guidelines, otherwise they should be removed from the service: https://docs.fedoraproject.org/en-US/packaging-guidelines/#_...
A package adhering to this guideline modifying system files, as designed, is not a problem. They are explicitly prohibited from modifying user data.
My point with managers vs scripts is that managers provide some sanity. Not perfection.
I trust:
- a versioned package
- built to the linked standards
- from upstream sources in an offline environment
Far more than I do curl | bash. There is far less ambiguity and I can actually reproduce this exact environment at some point.It’s a lot of busy work but we guaranteed that we had all dependencies in house and that the same package had the same layout of files across every OS
Authors better stick to traditional UNIX-style build system, which allows to pickup dependencies from local system without problems, and all distro-specific thing will be done by distro guys.
I've ported 10+ software packages to FreeBSD ports in last 20 years, on principle "I need this, it is not in the ports yet, make new port for it". Typically it takes 2x-3x time to single source build, i.e. one day top, if it is not something super-complex like KDE and it is possible at all (i.e. not very Linux-specific when FreeBSD doesn't have required APIs).
Modern build systems like npm and maven, which want to download and build all dependencies by themselves, are problem for this, I admit.
You need to use an appropriate license, you can't download stuff from the internet, you can't vendor libraries.
Ubuntu, Debian, Gentoo, Arch, etc., support third-party repositories and packages with bad licenses: the user adds the repo / installs the deb / etc. Pacman, in particular, even has direct support for such, and calls them out (to help ensure the user knows, and perhaps reads, the license).
Then I know I can gracefully uninstall the package by just asking the package manager to do that.
(You don't have to unvendor libs, either: if you install into something like /opt/$pakage_name, you can keep vendored libs in there. You should unvendor them, though.
Yeah, downloading stuff from the Internet in the middle of a package install is definitely harder with some package managers, but IMO that's a poor practice.)
Something like: https://getsum.pub
If you want to depend on system-wide stuff, or, worse yet, provide shared system-wide stuff, it's time to create a proper OS package (a bunch of them: Debian, Ubuntu, Fedora, Nix, etc).
The curl | bash approach has only one upside: you can store the script, inspect it, then run. I did that a couple times. Because otherwise it's a pretty scary operation, a very literal RCE.
Not having to waste countless hours on whatever distro's package format of choice is a pretty big upside.
And those are also RCEs if you're not upstreaming the package (which you likely are not because that increases the amount of time needed by an order of magnitude) as most package managers have multiple scripting points which run arbitrary code, and usually run as root already.
But it's not about you giving an rpm package at will. It's about the distro including packages in its official distribution and many people installing the very exact same package. Instead of people randomly pulling install scripts from the Web which can, for all we know, at every curl, be fetching a different install script.
In addition to that Debian has an ever growing number of packages which are fully reproducible, bit for bit. All these executables, reproducible bit by bit.
When I install a package from Debian I know many people have already both scrutinized it and installed it. It's not a guaranteed nothing shady is going on but what's safer:
- installing a Debian package (moreover reproducible bit for bit) which many people already installed
- curl bash'ing some URL at random
Anyone who says the two offer the same guarantees is smoking something heavy.
It's all too easy to sneak it in a backdoor for, say, once every 100 download when you moreover detect, as in TFA, that curl bash'ing is ongoing. And it's hard to catch. And it's near impossible to reproduce.
When you install from a package that's full reproducible: there's nowhere to run, nowhere to hide, for the backdoor once noticed. It shall eventually be caught.
Here's why it matters (FWIW there are tens of thousands of Debian packages which are fully reproducible):
https://reproducible-builds.org/
Thinking that installing a package "isn't really any better" than curl bash'ing from a URL is, plain simply, wrong.
yeah, if the package is delivered through the same channel as the bash script, and not anchored by anything external, you lose those benefits. but even hosting the package contents through pip or cargo or AUR or just unaffiliated and manually synced mirrors is a (relatively easy) way to decrease that attack surface.
Nobody has time to create packages for 8 different distros.
curl https://clickhouse.com/ | sh
The arguments are:- it's 'sh', not 'sudo sh', so it's not that bad;
- you can remove '| sh' and read the script;
- the deb, rpm, tgz, and docker packages are also provided, but only as advanced usage;
- nevertheless, all these packages, for all distributions, contain the same byte-identical ClickHouse binary.
It works surprisingly well. Even people without experience can copy-paste this command and start using our software.
Along the lines of "curl | bash" detection, one can add "sudo -n" to see if the person has passwordless sudo. In my own testing I have found that many people have passwordless sudo.
Even without sudo it turns out that people have bad posix permissions throughout their filesystem and one can hijack many things including existing SSH tunnels because of control-master. Even without sudo one can hop around a persons production network riding existing SSH channels. Many devops people have SSH multiplexing and control-master enabled in their SSH client. Then it is just a matter of finding bad permissions in production environments which is also often the case. One rarely needs root to download or even modify database contents as the database credentials are often stored in an environment file that gets sourced by automation.
The biggest problem here I see is that companies rarely let their penetration testers a.k.a. red-team into production. Corporate leaders would be taken aback at the findings.
But why can’t I copy the URL into my browser? Why discriminate on user agent? Why couldn’t it be https://clickhouse.com/install.sh - so that it would work with browsers and curl alike?
> - the deb, rpm, tgz, and docker packages are also provided, but only as advanced usage;
How are deb and rpm advanced? How do I uninstall something installed with your custom script? Also, why are the RPM packages [0] still using /etc/init.d and not systemd?
[0] https://clickhouse.com/docs/en/install/#from-rpm-packages
I think I'd always do it as an inline script. Admittedly I was slopping a lot of mud on the wall back then as a tactic.
if [ ! -t 0 ]; then echo "script must be run interactively, etc."; exit 1; fi
of course that's equally useless because as someone else said, the root problem with doing `curl | bash` in the first place is that you are putting the trust in someone else's server, so you can't fix that "server side". what the article is proposing is a whole lot of magic detect `curl | bash` from his safe server, where's it's already safe.I’ve yet to hear a coherent explanation why this is any worse than installing software from the internet in general. It’s not like you check the source of all software you install.
But 9 out of 10 times I used apt install cargo, I've been bitten by dependency hell
If canonical.com tells me to curl $url | sh, I'm fairly confident the script Im downloading is safe. as much as an .iso, .bin or .exe would be.
But I'd be a lot more hesitant doing the same from craigs-legit-swe-blog.com.
Now that nearly all URLs are HTTPS with valid certificates, the remaining risk seems to be that the host could be intentionally or unintentionally doing something destructive.
Sure it would be great to review the code of every install script before you run it, but as you allude to, it isn't practical.
Maybe something like ChatGPT could help us here?
if they ship a keylogger to every user, the odds of being noticed before they’re able to cleanly get away are substantially lower than if they ship that to a subset of users. so they may prefer to scam only 100 users, chosen by delivering a malicious payload to only every 1000th curl/https request for the source code. even if one of those users notices, said user will have a tough time confirming and attributing it.
now try doing that with a modern package manager. you can’t, because the package manager ensures every user gets the same code. you can still deliver different experiences at runtime — but you’re not likely to have the superuser privileges needed to run a leylogger or read ~/.ssh/id_rsa, etc, at that point.
it’s a safety in numbers game. i’m sure you play that game elsewhere in society. i won’t say it’s foolproof, but i’m not sure why it would seem incoherent to you when applied to the digital.
Keyloggers are trivial to do in userspace Linux via LD_PRELOAD attacks[0], and typically your user account has permission to read ~/.ssh/id_rsa.
I curl to files for review when I need / want to run a remote script. A bonus is you still have to `chmod u+x some_remote.sh` before it can be run, so it would be extremely difficult to accidentally run.
Makes me think of an idea -- and maybe it exists -- create a npm package whose only purpose is to run checks on the code of the other packages being installed to ensure they are "safe".