C – Safe execution of system() or exec() using environment variables

Safe execution of system() or exec() using environment variables… here is a solution to the problem.

Safe execution of system() or exec() using environment variables

I have two strings, both of which can be set by the user, eg

char *command = "vim $VAR";
char *myVar = "/tmp/something";

I want to use *myVar to perform *command for $VAR.

I tried concatenating them as environment variables (e.g. (pseudocode) system("VAR="+*myVar+"; "+ *command), but the user controls myVar so it would be very insecure and wrong.

I considered marking spaces to replace $var directly and passing the result to exec(), but was worried that it would be too awkward to mark shell command arguments correctly.

I

think the solution is by doing something like exec(“sh”, “-c”, command, “–argument”, “VAR", myVar), but I don’t see anything in the sh/dash/bash man page that allows environment variables to be set this way.

EDIT: I just saw execvpe(), which has a parameter to set the environment variable from the key=value string. Is it safe to enter with untrusted values?

How do I do this safely?

Solution

You can perform some string substitution on the value of myVar—put it inside single quotes, and replace all single quote (character ‘) strings ‘\' with four characters. If you don’t make implementation mistakes, it’s cumbersome but safe. If possible, use a library that does it for you

If your program is single-threaded, I recommend a different solution that doesn’t involve tedious references. You talked about setting environment variables… Well, let’s do it: set VAR as an environment variable.

setenv("VAR", myVar, 1);
system(command);
unsetenv("VAR")

I

omitted the error checking, and I’m assuming VAR isn’t needed elsewhere in the program (this solution becomes more tedious if needed because you need to remember the old values).

If you want fine-grained control over the environment in which commands run, you can do so in fork, execve (or execvpe) and waitpid, or in posix_spawn (or posix_spawnp) and > above waitpid. This requires more effort, but you can get Spirit Active.

Note that with the exception of string substitution for "vim $VAR” in the C program, the command needs to be vim “$VAR” and not vim $VAR regardless of your solution. This is because in shell syntax, $VAR only means “the value of the variable VAR” when it is inside double quotes—otherwise, $VAR means “take the value of VAR, split it into words, and expand each word into a filename wildcard pattern".

Related Problems and Solutions