Safeguard
Developer Tools•

Are shell completion scripts from a CLI safe to load?

A completion script is code your shell runs at every start. Generate it at install time, keep it static and review it like any other code your CLI ships.

Safeguard Security Team
3 min read

A completion script is shell code that runs whenever the user starts a shell, so treat it like any other code your CLI ships. Generate it at build or install time into a static file, keep it free of network calls, and avoid asking users to run your binary on every shell start.

The common pattern and its cost

Many CLIs ask users to add one line to a shell profile that runs the tool and evaluates its output. That line runs your binary, and whatever it prints becomes shell code, each time a terminal opens.

Three things follow.

  1. Startup cost. Launching a binary on every shell start slows terminals down, and people notice.
  2. Trust at every start. If the binary or its output changes, for example after a compromised update, the new code runs in the next terminal, before the user does anything.
  3. Invisible to review. The profile line looks harmless. The code it runs is not in the file.

A safer pattern

ApproachWhat runs at shell startReviewable
Evaluate the tool's output each timeYour binary, then its outputNo
Write the script to a file once, source the fileA static fileYes
Package manager installs the file in the system completions folderNothing extra from the profileYes

Prefer the second or third. Your install or update step writes the completion file. Users can read it, diff it between versions, and see it in backups.

What the script should contain

  1. Only completion logic: lists of subcommands and flags.
  2. No network requests. Completion that calls a remote API on every tab press is slow and leaks data about what the user types.
  3. No reading of secrets or environment values beyond what completion needs.
  4. No dynamic completions that run arbitrary project commands. If dynamic completion is needed, such as listing branch names, document what it executes.
  5. A header comment naming the tool version that generated the file.

Dynamic completion deserves care

Some tools complete values by running a subcommand, for example to list remote resources. If that subcommand reads project configuration, a hostile repository can influence it. Apply the same trust rules as the rest of your CLI. The trust prompt guide covers the model.

Update behaviour

When your CLI updates, regenerate the completion file, and write it atomically so a shell starting in the middle of an update never reads half a file. Remove the file on uninstall so no stale code is left behind.

Document it

In your install docs, show the file-based setup and explain why. Also tell users how to see what their profile loads.

Quick check

Is evaluating completion output in a profile unsafe?

It is a trust decision made at every shell start. A static file written once is easier to review and does not run your binary each time.

Should completions call the network?

Avoid it. It slows typing and can reveal what the user is working on.

If you want to know which packages your CLI ships, Safeguard's free scan at gold.safeguard.sh/scan produces an inventory.

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.