3

What is the best and most correct way to use Linux commands in bash scripts in terms of path to it?

Is that correct to use only ip addr show, relying on shell path ($PATH), or should I find a path to the command first (like with whereis ip or command -v ip), assign the output to some variable and then use that?

hakre
  • 193,403
  • 52
  • 435
  • 836
sys463
  • 337
  • 2
  • 5
  • 18
  • 1
    Both of those use `PATH` to determine an absolute path, so it's a useless intermediate step. – chepner Nov 07 '18 at 20:06
  • 2
    I wish I had time to write a detailed answer. Cliff notes: Use plain commands and don't worry about `$PATH`. Storing absolute command paths in variables is a common anti-pattern. `$PATH` is under the user's control, so if it's not set right, that's their own fault. There's nothing they can exploit by changing it; they can always run a script's commands by hand, after all; or just edit the script and then run it. You only need to be careful with `$PATH` if you elevate privileges. For instance, you'll see that `su` and `sudo` have protections to prevent exploits. – John Kugelman Nov 07 '18 at 20:23
  • Thanks for your comment, @JohnKugelman – sys463 Nov 08 '18 at 08:05

3 Answers3

5

Personally, I just rely on the PATH and invoke "bare" commands.

If you don't trust the user's PATH, you can reset it to a minimal default:

PATH=$(/usr/bin/getconf PATH)

grep "$pattern" "$file"
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
1

Old question, and in concrete it is not practically answerable to its full extend as we don't know the environment when the scripts gonna run. Therefore:

# early pipe for smoke testing required commands
hash test for false promises || exit 1

just line-up the important, non-standard commands you require very early in the script by their name only and if one is not found, hash will tell:

hash: no such command: for
hash: no such command: promises

Rationale: Exit the script early unsuccessfully before getting stuck in the middle wasting your precious time and potentially leaving a transaction on the system open in the middle and unfinished and instead direct the action back to the user that can control the runtime environment (fail-fast1).

This works well together with the accepted answer in the sense that you can use that answer for removing side-effects (and make the configuration by system-administrators autoritative) but likely even more with the remark from John Kugelman who commented afterwards to "Use plain commands and don't worry about $PATH"2

Fail early, fail often, but always fail forward.

-- John C. Maxwell


  1. fail-fast, https://en.wikipedia.org/wiki/Fail-fast
  2. I wish I had time to write a detailed answer. Cliff notes: Use plain commands and don't worry about $PATH. Storing absolute command paths in variables is a common anti-pattern. $PATH is under the user's control, so if it's not set right, that's their own fault. There's nothing they can exploit by changing it; they can always run a script's commands by hand, after all; or just edit the script and then run it. You only need to be careful with $PATH if you elevate privileges. For instance, you'll see that su and sudo have protections to prevent exploits. [bold by me]

    John Kugelman; Nov 7, 2018 at 20:23

hakre
  • 193,403
  • 52
  • 435
  • 836
-2

I tend to set the path to utilities at the top of my path, avoiding any dependency on PATH. One potential attack is to set the PATH before running a bash script. Setting the path for each utility is painful, but it can protect against that sort of attack.

In cases where you are authoring for multiple environments in which the utilities are found in different places, e.g. Debian and MacOS, I check for the path, e.g.

[ -f /usr/bin/grep ] && GREP=/usr/bin/grep || GREP=/bin/grep
CharlieH
  • 1,432
  • 2
  • 12
  • 19
  • What attacks are you concerned about preventing, exactly? – John Kugelman Nov 07 '18 at 20:01
  • 2
    If you don't trust PATH you can simply set it to a known good value at the start of your script. Better than this cargo cult anti-pattern of storing command names in variables that I see so often. – John Kugelman Nov 07 '18 at 20:03
  • Or, the untrusted user can just edit your script to use the `grep` of their choice. If anything, this makes it easier to do so, because only one assignment needs to be changed. – chepner Nov 07 '18 at 20:11
  • @JohnKugelman yes, setting the PATH at the top is one way. The attack would be that the PATH is somehow changed outside of the script, and the script that normally does one thing could do something completely different. – CharlieH Nov 07 '18 at 21:31