saleyn / erlexec

Execute and control OS processes from Erlang/OTP
https://hexdocs.pm/erlexec/readme.html
Other
525 stars 139 forks source link

provide facility for unsetting environment variables #133

Closed mk270 closed 4 years ago

mk270 commented 4 years ago

It's not clear (from some perusal of the C++ and docs) that there's any way of unsetting environment variables to prevent them being passed to the subprocess; I am trying to avoid polluting that environment / potentially exposing random variables which have been inherited by Erlang.

saleyn commented 4 years ago

The environment of a child process is inherited from the port process, which you can customize with the {env, Env} option: https://github.com/saleyn/erlexec/blob/master/src/exec.erl#L103. This list can unset the variables you don't need. But currently there's no option to clear all environment.

mk270 commented 4 years ago

Yes, I'm aware of {env, Env}, but it's not clear how to use it to unset variables that are set in the port process. You can set them to the null string, but I don't see how to unset them, or to enumerate them.

saleyn commented 4 years ago

Enumerate by running the exec:run("env", [{sync, stdout}]) command, and unset with {env, [{"MYVAR", ""}]}. Not very convenient, but a patch that addresses such functionality is welcome. Though the project has been around for a while, and so far no other users have had a need for this feature.

mk270 commented 4 years ago

Ah, we're using different definitions of "unset" (I'd call {env, [{"MYVAR", ""}]} setting MYVAR to the null string rather than unsetting it.

Is there a way to avoid having a variable appear in the subprocess environment at all?

saleyn commented 4 years ago

Currently no.

mk270 commented 4 years ago

Ok, well, I would like some mechanism and if I can write one in the next few months I shall send a Pull Request.

This is useful because it can protect against two real-world problems (neither of which is particularly important, but we should not make it nearly impossible to fix them):

saleyn commented 4 years ago

It seems that a proper solution would be to sanitize the environment prior to starting the Erlang VM, since other programs that are spawned from the Erlang OS process (such as the ones executed by erlnag:open_port/2 or os:cmd/1) still inherit VM's environment.

There's an easy way to clear environment in a shell by prefixing your command with env -, e.g.:

exec:run(["/usr/bin/env", "-", "env"], [sync, stdout]).

The drawback of this though is that you would need to set the environment variables that you want to set as part of the command line, as the {env, Env} option will be cleared:

exec:run(["/usr/bin/env", "-", "MYVAR=1", "env"], [sync, stdout, {env, [{"TEST", "1"}]}]).
{ok,[{stdout,[<<"MYVAR=1\n">>]}]}

As far as adding support for it - the solution is quite simple. Upon passing a new command option that would clear the environment, it's just necessary to skip copying parent process's environment in the port program, which is done here. I would accept a PR that implements it, if you this feature is useful to you.

saleyn commented 4 years ago

This feature is implemented in the latest commit. Use {env, [clear]} option to clear all environment, and {env, [{"VAR", false}]} to unset a variable.

mk270 commented 4 years ago

Thank you very much indeed. I shall check this out, but by your description I believe it solves the two problems I'm actually dealing with.