Variable substitution and command substitution is done in two passes. This means if variable substitution results in a string containing $(command) that command is executed. I think this is unexpected, it isn't mentioned in the README in the section Command Substitution. This further means if some seemingly innocuous environment variables are user controlled and then referenced in the .env file this will execute any command in them.
This can be fixed by doing both variable substitution and command substitution in one pass instead of two.
(Personally I don't think command substitution is a good feature anyway, and it should be at least deactivated by default.)
{"FOO"=>"$", "BAR"=>"(date)", "BAZ"=>"Fr 14 Jun 2024 17:49:33 CEST"}
The command substitution doesn't need to be split over several variables, I just did this to demonstrate that even if that is done it works. Also the variables containing the command substitution syntax don't need to come from the .env file. They could be already in the environment. While I can't think of a situation where user input may control an environment variable that then is used in a .env file right off my head, I still consider that a potential problem. There's probably some obscure script somewhere that uses things like that. (The only similar situation I can think of are classical CGI scripts where HTTP headers are passed as environment variables, but Ruby isn't usually used as a CGI script and even then the HTTP header variables need to be referenced in the .env file, which is unlikely.)
Expected behavior
I think it should print this, and don't execute any commands:
{"FOO"=>"$", "BAR"=>"(date)", "BAZ"=>"$(date)"}
Actual behavior
Executes the command date in this case, or any command generally.
Variable substitution and command substitution is done in two passes. This means if variable substitution results in a string containing
$(command)
that command is executed. I think this is unexpected, it isn't mentioned in the README in the section Command Substitution. This further means if some seemingly innocuous environment variables are user controlled and then referenced in the.env
file this will execute any command in them.This can be fixed by doing both variable substitution and command substitution in one pass instead of two.
(Personally I don't think command substitution is a good feature anyway, and it should be at least deactivated by default.)
Steps to reproduce
Put this in a
.env
file:Then run e.g.:
Which prints:
The command substitution doesn't need to be split over several variables, I just did this to demonstrate that even if that is done it works. Also the variables containing the command substitution syntax don't need to come from the
.env
file. They could be already in the environment. While I can't think of a situation where user input may control an environment variable that then is used in a.env
file right off my head, I still consider that a potential problem. There's probably some obscure script somewhere that uses things like that. (The only similar situation I can think of are classical CGI scripts where HTTP headers are passed as environment variables, but Ruby isn't usually used as a CGI script and even then the HTTP header variables need to be referenced in the.env
file, which is unlikely.)Expected behavior
I think it should print this, and don't execute any commands:
Actual behavior
Executes the command
date
in this case, or any command generally.System configuration
dotenv version: dotenv 3.1.2
Ruby version: ruby 3.3.2 (2024-05-30 revision e5a195edf6) [x86_64-linux]