> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BEST-PRAC-1 — Command piped directly to shell

> curl | sh and wget | bash patterns are vulnerable to MITM and supply-chain compromise.

| Field    | Value         |
| -------- | ------------- |
| Category | `BEST-PRAC-1` |
| Severity | **HIGH**      |
| Auto-fix | ✗             |

## What the check does

Flags any `run:` script (GitHub Actions **and** GitLab CI) that pipes a network fetch straight into an interpreter:

```
(curl|wget|iwr|invoke-webrequest) <anything-without-pipes> | [sudo] (sh|bash|zsh|ksh|dash|python3?|iex|node|perl|ruby)
```

This covers the common evasions of a naive `curl | sh` match: an intervening `sudo`, flags like `bash -s`, non-shell interpreters (`python3`, `node`), and PowerShell's `iwr … | iex`.

## Why it matters

`curl https://example.com/install.sh | sh` downloads a remote script and pipes it directly into the shell. Risks:

* The remote host (or anyone in path) can serve different bytes on the next request.
* A compromise of the distribution endpoint becomes immediate arbitrary execution on your runner — with whatever secrets and permissions the workflow has.
* The script can detect it's being piped (by reading file descriptors) and serve a benign version to inspectors and a malicious one to executors.

## Vulnerable example

```yaml theme={null}
- run: curl -sSL https://get.example.com/install.sh | bash
```

## Safe alternatives

**1. Use a pinned official action.** Most popular installers publish a `setup-foo` action — pin it to a commit SHA per [CICD-SEC-3](/rules/cicd-sec-3).

```yaml theme={null}
- uses: example/setup-foo@<sha> # v2
```

**2. Download, verify, then run.** Check a known checksum before execution:

```yaml theme={null}
- run: |
    curl -sSL https://get.example.com/install.sh -o install.sh
    echo "<known-sha256>  install.sh" | sha256sum -c -
    bash install.sh
```

**3. Bake the installer into a container image** you control, then `runs-on:` that image.

## Why no auto-fix

There's no safe automatic rewrite — the correct fix depends on whether an official action exists, what the expected checksum is, and what the surrounding flags do. This check is reported for human review.
