The Exim mail server has, among other features, a string expansion language with quite a number of expansion operators . One of those expansion operators is '
${run}
', which 'expands' by running a command and substituting in its output. As is commonly the case, ${run} is given the command to run and all of its command line arguments as a single string, without any explicit splitting into separate arguments:
${run {/some/command -a -b foo -c ...} [...]}
Any time a program does this, a very important question to ask is how this string is split up into separate arguments in order to be exec()'d. In Exim's case, the traditional answer is that it was rather complicated and not well documented , in a way that required you to explicitly quote many arguments that came from variables. In my entry on this I called Exim's then current behavior dangerous and wrong but also said it was probably too late to change it. Fortunately, the Exim developers did not heed my pessimism.
In Exim 4.96, this behavior of ${run} changed. To quote from the changelog:
The ${run} expansion item now expands its command string elements after splitting. Previously it was before; the new ordering makes handling zero-length arguments simpler. The old ordering can be obtained by appending a new option "preexpand", after a comma, to the "run".
( The new way is more or less the right way to do it , although it can create problems with [[some sorts of command string expansions .)
This is an important change because this change is not backward compatible if you used deliberate quoting in your ${run} command string . For example, if you ever expanded a potentially dangerous Exim variable in a ${run} command (for example, one that might have a space in it), you previously had to wrap it in ${quote}:
${run {/some/command \
--subject ${quote:$header_subject:} ...
(As seen in my entry on our attachment type logging with Exim .)
In Exim 4.96 and later, this same ${run} string expansion will add spurious quote marks around the email message's Subject: header as your program sees it. This is because ${quote:...} will add them, since you asked it to generate a quoted version of its argument, and then ${run} won't strip them out as part of splitting the command string apart into arguments because the command string has already been split before the ${quote:} was done. What this shows is that you probably don't need explicit quoting in ${run} command strings any more , unless you're doing tricky expansions with string expressions (in which case you'll have to switch back to the old way of doing it).
To be clear, I'm all for this change. It makes straightforward and innocent use of ${run} much safer and more reliable (and it plays better with Exim's new rules about 'tainted' strings from the outside world, such as the subject header). Having to remote my use of ${quote:...} is a minor price to pay, and learning this sort of stuff in advance is why I build test servers and have test plans.
(This elaborates on a Fediverse post of mine .)