curl | sh: what it executes, why it's risky, and how to vet scripts
curl | sh is a high-severity command AI coding agents run without human checkpoints. DestructGuard's strict tier blocks the pattern at execution time and logs every approve-or-abort decision to a JSONL audit trail you can replay with IncidentScribe.
curl | sh
Blast radius
Whatever the remote server returns at the moment of the request runs with the caller's shell privileges. A compromised TLS endpoint, a server-side hijack, a CDN edge takeover, or a DNS poisoning at the moment of execution all yield arbitrary code execution. Most installers `set -e`, so errors abort — but the malicious portion has usually already run.
The safer pattern: download, inspect, then run
Split the pipe into three auditable steps: `curl -fsSL https://example.com/install.sh -o install.sh`, read it (or diff against a known checksum/signature), then `sh install.sh`. This defeats the classic pipe-detection trick where a server returns different content when it detects streaming to a shell, gives you a saved artifact for the audit trail, and lets a blocklist rule allow the download while still gating the execution step on a human approval.
Why agents reach for it
Agents reach for it when installing CLIs (`curl https://install.example.sh | sh`), bootstrapping environments, and following third-party README quick-start instructions verbatim. The risk surface is highest with typosquatted domains and unsigned binaries.
Recovery options
No technical rollback — by the time the response is in the shell's read buffer, every command has been parsed and executed. Forensic recovery: `~/.bash_history` may capture the command but not the script body; `auditd` (if enabled) logs exec calls; snapshots of the install paths may show what was added or modified.
Real-world incident
An agent piped curl into sh from a URL that had been typosquatted by one character. The script exfiltrated SSH keys and AWS credentials, modified `~/.bashrc` to install a persistent SSH key, and returned a successful exit code to the agent — the operator didn't notice for three days.
Block it with DestructGuard's strict tier
DestructGuard's strict rules tier includes curl | sh by default — the call is intercepted at the shell or process boundary before execution. Approvals are logged to JSONL with timestamp, caller, command, and decision. Pair with git pre-commit and pre-push hooks from the Pro Pack so destructive patterns are blocked at multiple points in the agent pipeline.
From guidance to an enforceable agent loop
Preflight this command before an agent executes it
Start with the one-cent Action Safety Quick Gate. Low risk can proceed, medium risk routes to full DestructGuard evidence, and high or critical risk routes to the complete workflow for ReviewQueue triage, a signed receipt, and a privacy-preserving status record. Triage never implies human approval.