Skip to content
Advertisement

PHP – Does $setting need to be escaped in a ‘putenv’ call?

The putenv function takes a single argument, a string. This string is expected to take the following format: KEY=VALUE.

Reference: http://php.net/manual/en/function.putenv.php

Take the following code as a potential use case:

if(getenv(ON_SOME_ENVIRONMENT)) {

  // What happens if $dir contains an '=' character?
  $dir = dirname(__FILE__);

  putenv('SOME_KEY=' . $dir);
}

Does $dir in the above example need to be escaped? If so, what kind of escaping needs to happen?

Advertisement

Answer

I’m not sure the right answer, but I hope this can help.

In general, filtering user inputs depends on the context where the input is being used and what is a control character in that context. It seems that = is a control character that you want to avoid being interpreted as a control character, so that’s one thing to filter. If there is an appropriate language built-in function you can use to do filtering that is the RIGHT one for that context then you should use that function. For example, as I guess you know, escapeshellarg is the right thing to use for shell arguments before passing user input to exec(). I don’t see a similar function to use before calling putenv. If you can make the filter based on an allowlist approach that’s generally stronger. For example, just allowing ASCII alphabet from a-z would be a good way to allow English names without letting control characters sneak in for most scenarios.

Another strategy to protect against malicious input is to use an allowlist approach instead of (or in addition to) a filtering approach. So, if you know that accepted inputs are ASCENDING or DESCENDING then instead of providing a text box to users give them a dropdown and ensure that they selected either ASCENDING or DESCENDING before using it in the putenv function (ASCENDING and DESCENDING are random examples of things that might be expected, but adjust for your scenario). This doesn’t work if the user input can be a wide variety of things, of course.

Some practical tests:

It does seem like some of the behavior is version and/or platform dependent.

With PHP 7.3 on MacOS I got the same results as @michfuer.

Doing that same test on a ddev docker container running Linux 5.10.25-linuxkit and PHP 7.4 I get different results:

$ php -a
Interactive mode enabled
php > putenv('SOME_KEY=foo/bar=baz');
php > var_dump(getenv('SOME_KEY'));         // value "foo/bar=baz"
string(11) "foo/bar=baz"
php > var_dump(getenv('SOME_KEY='));        // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME_KEY=foo'));     // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME_KEY=foo/bar')); // value "foo/bar=baz"
string(3) "baz"
php > var_dump(getenv('SOME_KEY=blarg'));   // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME'));             // value false
bool(false)
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement