Some Linux distributions, probably most prominently NixOS, do not have their shells in e.g. /bin/bash, but in a different directory instead. For this reason, shells should be spawned via the env command, which executes the shell via $PATH lookup. Scripts using e.g. /bin/bash are incompatible with such distributions.
(Those distros have chosen to put only env in a hardcoded location for compatibility, while everything else lies wherever $PATH says it does.)
#!/bin/bash
echo "Hello World"
Use
/usr/bin/env bashinstead of/bin/bash
I beg to differ. I only want a warning for the opposite, using env to find the shell, because that leads to security problems if PATH is tainted, or elements in $PATH are insecure.
Systems have been hacked due to this misuse of env. One of the first things a hacker checks for is if /usr/local/bin has write permissions (some systems do) or is NFS mounted (many older systems are), and is earlier in the path than where the real bash is. Then plop in a replacement bash there, and wait for root to execute a script that has env bash.
I strongly concur with @arth1; I do _not_ recommend this practice for "installed" scripts. It's often suggested as a work-around for scripts that are published as stand-alone entities for newbies to use without modification, but that leads to them thinking that they should write their own scripts using that pattern, but they shouldn't.
My reasons are substantively the same as arth1's:
env is that it expands $PATH before the shell or the script gets a chance to sanitise it. This leaves a window for compromise or misbehaviour.chmod a+x, but not the whole story: as part of installing any program its dependencies should be resolved. For a script that includes setting the path to the interpreter. Because these paths vary from system to system even when the version is the same, it should be done _once_ per host (per version of the script).So there's an argument to be made that a script (say thescript.bash) should be distributed without a #! line at all, but with instructions that after downloading, it can be installed using something like:
install -m 555 <( printf '#!' ; type -p bash ; cat thescript.bash ) "$HOME"/bin/thescript
I see your points. I'll have to do this on a case-by-case basis then. Luckily, it's not more than a bit of grep/sed to do so.
Most helpful comment
I beg to differ. I only want a warning for the opposite, using env to find the shell, because that leads to security problems if PATH is tainted, or elements in $PATH are insecure.
Systems have been hacked due to this misuse of env. One of the first things a hacker checks for is if /usr/local/bin has write permissions (some systems do) or is NFS mounted (many older systems are), and is earlier in the path than where the real bash is. Then plop in a replacement bash there, and wait for root to execute a script that has env bash.