My apologies for the duplicate thread on this.
The E: format modifier (
format.c:5242)
calls format_expand1() on the resolved value of a variable. Because
format_expand1() processes #() directives, any variable whose resolved
value contains #() will have that content executed as a shell command.
For example, if a user configures:
set -g status-right '#{E:pane_title}'
and the pane title contains "#(id)" -- whether set by an escape
sequence, a script, or any other means -- the id command runs every
time the status line redraws.
This
applies to any variable used with E: in a context where jobs are
enabled (status-left, status-right, window-status-format,
pane-border-format, etc.). It is not specific to pane_title.
In
practice, any program output displayed in a tmux pane can set these
variables via standard escape sequences, such as curling a URL, cat'ing a
file, tailing a log, or connecting to a remote host over SSH. These are
routine operations where the user does not expect terminal output to
influence command execution.
The user has no reason to expect
this. The default status-format template uses E: approximately 25 times
(on style options), so the modifier appears safe for general use.
Nothing documents that E: causes resolved variable values to be
evaluated as format strings including #() shell execution.
The existing FORMAT_EXPAND_NOJOBS mechanism already prevents this class of issue in one place: format_job_get() (
format.c:386)
sets FORMAT_EXPAND_NOJOBS before re-expanding #() output, blocking
nested command execution. But the E: path at format.c:5242 does not set
this flag, so #() in re-expanded values is executed.
Proposed fix: Set FORMAT_EXPAND_NOJOBS before the E: re-expansion, matching the existing pattern at line 386:
if (modifiers & FORMAT_EXPAND) {
- new = format_expand1(es, value);
+ struct format_expand_state next;
+ format_copy_state(&next, es, FORMAT_EXPAND_NOJOBS);
+ new = format_expand1(&next, value);
free(value);
value = new;
}
This
prevents #() execution during E: re-expansion while preserving all
other format expansion (variable lookups, conditionals, etc.).
Legitimate uses of E:, primarily re-expanding style options, do not use
#() and are unaffected.
To reproduce:
tmux set -g status-right '#{E:pane_title}'
printf '\033]2;#(touch /tmp/test-e-modifier)\007'
tmux refresh-client
ls /tmp/test-e-modifier
Tested on current master (8356578a)
Cheers,
Mason