Closed mk270 closed 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.
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.
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.
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?
Currently no.
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):
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.
This feature is implemented in the latest commit. Use {env, [clear]}
option to clear all environment, and {env, [{"VAR", false}]}
to unset a variable.
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.
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.