Search code examples
phpsecuritycodeigniter-4.env

Codeigniter 4 .env variables in $_SERVER?


As part of debugging an application I'm logging the $_SERVER variable to my log table. I noticed that the custom settings from the .env file are included in the $_SERVER variable, including database credentials. Is this normal? Seems like a very bad idea.

For example, the following is included when I get the contents of $_SERVER (data is JSON formatted for logging):

...    
"CI_ENVIRONMENT":"production",
"database.default.hostname":"localhost",
"database.default.database":"app",
"database.default.username":"app_user",
"database.default.password":"*REDACTED*",
"database.default.DBDriver":"MySQLi",
...

Since this is a server only variable I don't have specific concerns with this I guess, but it was shocking to see the database credentials in the log table where I had no expectation they would end up.


Solution

  • Explanation:

    Is this normal? Seems like a very bad idea.

    In reference to vanilla PHP and Apache/Nginx web server, you wouldn't find .env file environment variables in the $_SERVER superglobal variable.

    However, in the world of CodeIgniter 4, at the time of writing this post, all configured .env file environment variables are copied to the $_ENV and $_SERVER superglobal variables if they don't exist already.

    Excerpt from CodeIgniter4/public/index.php

    // Load environment settings from .env files into $_SERVER and $_ENV
    require_once SYSTEMPATH . 'Config/DotEnv.php';
    (new CodeIgniter\Config\DotEnv(ROOTPATH))->load();
    

    Excerpt from CodeIgniter4/system/Config/DotEnv.php

        protected function setVariable(string $name, string $value = '')
        {
            if (! getenv($name, true)) {
                putenv("{$name}={$value}");
            }
    
            if (empty($_ENV[$name])) {
                $_ENV[$name] = $value;
            }
    
            if (empty($_SERVER[$name])) {
                $_SERVER[$name] = $value;
            }
        }
    

    I'm not sure why .env file environment variables were copied to the $_SERVER superglobal variable, but I assume it was done for convenience.

    As far as security of the contents of the $_SERVER superglobal variable, please refer to Which $_SERVER variables are safe?

    Solution

    Since this is a server-only variable I don't have specific concerns with this I guess, but it was shocking to see the database credentials in the log table where I had no expectation they would end up.

    I was also surprised to notice that kind of behavior.😮 Nonetheless, as a solution to your issue, instead of logging the $_SERVER superglobal variable, log the result of this:

    array_diff($_SERVER, $_ENV);
    

    This will give you an associative array that doesn't have .env file environment variables.