Your extension is something with many useful features, but sadly it appears to be very inflexible with respect to defining tasks, and I suspect it's due to something that was overlooked instead of intentional.
In my version, 0.1.4, you replace the user defined command with the shell that may be supplied by the user or else a default, and then you supply the arguments -c and the user supplied arguments to node js's spawn. Or at least, this is what I traced in the extension.
This is very inflexible for the following reasons:
- The
-c argument prepending to user arguments is not optional in at least some cases, but not all shells use that string to go before the command to execute.
- The user arguments are appended, but if you have
-c before it, they must form one single argument, not several. This means supplying any user arguments at all creates a command that does not do what it should. I will illustrate.
const taskJson = {
// some fields omitted
command: "deno",
args: ["eval", "console.log('Hello')"],
};
// Then you effectively get something that does not work (in fact it hangs):
spawn("/bin/bash", ["-c", "deno", "eval", "console.log('Hello')"]);
// You *should* get a single argument to follow "-c", due to shells expecting the command as such:
spawn("/bin/bash", ["-c", "deno eval 'console.log(\"Hello\")'"]);
I think I get why this is your approach, because you want to prevent injection but still allow the choice of shell. I think that is not possible. The best you can do is escape all single quotes as required by the supported shells, and wrap the single argument that should be passed in single quotes. At least in bourne-like shells and powershell this prevents expansion of variables and so on.
I worked around this by making my snippet texts be outputted by no-argument wrapper commands, and executing those, but that is more work than needed.
I suggest omitting the wrapping of the command in a shell that the user chooses, and letting them set it in the task itself if they want. They can simply put the shell as the command if they want a different one.
const taskJson = {
// some fields omitted
command: "pwsh",
args: ["-Command", "get-date -UnixTimeSeconds 0"],
};
Your extension is something with many useful features, but sadly it appears to be very inflexible with respect to defining tasks, and I suspect it's due to something that was overlooked instead of intentional.
In my version, 0.1.4, you replace the user defined command with the shell that may be supplied by the user or else a default, and then you supply the arguments
-cand the user supplied arguments to node js'sspawn. Or at least, this is what I traced in the extension.This is very inflexible for the following reasons:
-cargument prepending to user arguments is not optional in at least some cases, but not all shells use that string to go before the command to execute.-cbefore it, they must form one single argument, not several. This means supplying any user arguments at all creates a command that does not do what it should. I will illustrate.I think I get why this is your approach, because you want to prevent injection but still allow the choice of shell. I think that is not possible. The best you can do is escape all single quotes as required by the supported shells, and wrap the single argument that should be passed in single quotes. At least in bourne-like shells and powershell this prevents expansion of variables and so on.
I worked around this by making my snippet texts be outputted by no-argument wrapper commands, and executing those, but that is more work than needed.
I suggest omitting the wrapping of the command in a shell that the user chooses, and letting them set it in the task itself if they want. They can simply put the shell as the command if they want a different one.