"Just run this, it's fine."
Imagine a stranger hands you a sealed envelope and says, "Read this out loud on stage, it's fine." You don't know what's inside. You can't review it before speaking. And if someone swapped the envelope on the way to you, you'd never know.
That is exactly what curl | bash does. You have probably seen instructions like this in install scripts or CI steps:
curl -sL https://example.com/install.sh | bash
The pipe (|) sends the downloaded content directly to bash for execution without ever saving it to disk. It is convenient, but from a security perspective, it is one of the most dangerous patterns in DevOps.
Why It Is Dangerous
1. No Verification — You Execute Blindly
The script runs before you can inspect it. You have no idea what it does. Even if you trust the source today, you cannot guarantee the source hasn't been compromised since the last time you checked.
2. Man-in-the-Middle (MITM) Attacks
A MITM attack occurs when an adversary intercepts network traffic between two parties. If the script is served over plain HTTP (not HTTPS), or if the attacker has compromised a network device between your runner and the server, they can replace the script content in transit with anything they want — a crypto-miner, a backdoor, or a command that exfiltrates your secrets.
Even HTTPS is not a complete defense if the origin server itself is compromised.
3. Partial Execution on Network Failure
If the network connection drops halfway through the download, bash receives and executes only the first half of the script. This can leave your system in a broken, undefined state — with some commands having run and others not. Debugging this is extremely difficult.
4. No Audit Trail
Because the script is never saved to disk, there is no record of exactly what ran. This makes forensic investigation after an incident nearly impossible.
The Fix: Download, Verify, Then Execute
Always download the script first, verify its integrity against a known-good checksum obtained from a trusted, separate source, optionally inspect it, and only then execute it — never pipe an unverified download straight into an interpreter.
For even stronger guarantees, pin to a specific Git commit SHA or a container image digest rather than a mutable version tag:
# GitHub Actions: Pinning an action to a specific commit SHA
# BAD: uses: actions/checkout@v4 (mutable tag — can be changed by the author)
# GOOD: pin to the exact commit that v4 pointed to at time of review
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
This ensures that even if the tag is moved or the repository is compromised, your pipeline runs exactly the code you reviewed.
Interviewers frequently ask: "How would you harden a CI pipeline that installs third-party tools?" The answer they want covers three things: (1) pinning to immutable references (commit SHAs or image digests, not tags), (2) checksum verification before execution, and (3) preferring vendored or pre-baked dependencies in a trusted base image over downloading at runtime. Mentioning the SolarWinds supply chain attack as motivation for this discipline demonstrates senior-level awareness.