The best way to get informed about how capturex operates is by looking at its source.

The sub implements its own piped open in "list-form", to work around the (ancient!) v5.6.x limitations. It does so by fork -ing a process using piped open and then "manually" exec -ing the command in the child, where it can use the list-form. Then the output is read in the parent. Follow the word "pipe" in the open page, and then the link to perlipc.

So there can be no shell involved since exec in the LIST form uses execvp(3) system call to directly run the command. (What may happen when it runs with a single argument as well, if it contains no shell meta-charactes.) Thus the characters that (would) have a special meaning in the shell may be used freely as literal characters in the command.

As for the second question -- if a command is formed with user-input it must always be checked really carefully! Note that one shouldn't literally use input in a command, but rather support keywords and parameters based on which the program composes the command. Avoiding the shell of course helps but any user input must be checked.

The injection bug is more of a programming error, whereby variable interpolation isn't used right and results in an unintended command; there is no need for malicious acts there, just for the "right" input that exposes the bug.