Environment variables are a pretty common way of communicating with a child process. You might just as well ask "why is it allowed to pass arguments to a child process?" Of course, with environment variables a little more precaution is necessary, because some environment variables (PATH
, for example) affect the semantics of some system calls. So the usual convention is to restrict the environment variables which can be set from untrusted input to a set of known names.
For example, the CGI protocol -- which uses environment variables to communicate information about the HTTP request -- restricts itself to a set of environment variable names specified in what loosely might be described as the CGI standard, plus arbitrary environment variables whose names begin with the characters HTTP_
.
While CGI has possibly the largest inventory of user-input environment variables, the technique is pretty common. One well-established example is the use of TERM
to define the terminal type of a remote terminal, but there are lots more.
Environment variables, like command-line parameters, need to be treated with care, and sometimes barriers are needed. The /bin/env
utility provides a mechanism to clean the environment given to an executable, for example; that's useful if the environment is not trustworthy and essential if the executable is running with elevated privileges.
Aside from specific cases (like PATH
), no application should rely on an environment variable being clean. Doing something on the basis of an environment variable's value without first checking its validity is as much of a bug as any other unvalidated use of user-provided data. (q.v. SQL injection attack.) And that's what we have here: a bug, plain and simple. These things happen. We're not perfect. (The fact that this bug has been present for over two decades apparently without anyone noticing is, at least, interesting.)