5 Answers
5

Probably to keep the kernel simpler. I don't think the kernel ever searches your path to find an executable. That's handled by the C library. #! processing is done in the kernel, which doesn't use the standard C library.

Also, I don't think the kernel has a notion of what your path is. $PATH is an environment variable, and only processes have an environment. The kernel doesn't. I suppose it could access the environment of the process that did the exec, but I don't think anything currently in the kernel ever accesses environment variables like that.

The reason that depending on PATH is not considered good practice is that the script can make no assumptions about the content of the PATH environment variable, breaking the "sequential dependency model" of binaries where

/bin contains the executables needed at boot time;

/usr/bin contains the other executables used by the OS installation;

/usr/local/bin contains executables installed by the system administrator that are not part of the base OS.

~/bin contains the user's own executables.

Each level should not assume the existence of binaries later in the sequence, which are more "application" but may rely on binaries earlier, which are more "fundament". And the PATH variable tends to run from applicationy to fundamental, which is the opposite direction to the natural dependency above.

To illustrate the problem, ask yourself what happens if a script in ~/bin invokes an script in /usr/local/bin that invokes Ruby? Should that script depend on the OS installed version at /usr/bin/ruby, or on the personal copy the user happens to have at ~/bin/ruby? PATH searching gives the unpredictable semantics associated with the latter (maybe ~/bin/ruby is a broken symbolic link), while baking in the path to #! gives the former.

There isn't really any other platform-independent "operating system ... information regarding the path for a registered command", so the simplest thing is to insist on the path being provided in the #!.

There are other reasons, but from a security perspective I would never want a script to make assumptions about the correct path. What if it is wrong and it runs the wrong shell or interpreter? One that has been inserted by a malicious user? Or what if it relies on a particular shell and will crash out if the wrong shell is used?

Users may mess around with their path and break stuff - don't trust the user:-) I have conducted numerous attacks which rely on the user doing the wrong thing with their path - usually getting things in the wrong order - so I can subvert a normal script call.

Yes, I know if you've written the script yourself you can quite rightly claim that you have sorted out your own path, but an interpreter can't make those decisions.

Your point about setxid is valid, however it is a perfectly useful attack vector so definitely isn't a false warning
–
Rory AlsopApr 24 '11 at 16:16

1

Could you give an example of a case where PATH is an attack vector, and there aren't so many other attack vectors that the whole approach should be rethought?
–
GillesApr 25 '11 at 17:38

@Gilles - +1 you have a good point, definitely, as if this is broken there are probably other ways in that are just as valid, however in terms of broken things you can fix, this is an easy one.
–
Rory AlsopApr 26 '11 at 7:46