help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

how to expand only parameters with no side-effects in a command string


From: Christoph Anton Mitterer
Subject: how to expand only parameters with no side-effects in a command string
Date: Tue, 03 Oct 2023 23:59:46 +0200
User-agent: Evolution 3.50.0-1

Hey there.

I'd have another question for the benefit of fzf's bash/completion
integration.

When performing fzf's completion (via `**<TAB>`), fzf would try to
expand parameters in the current word (i.e. ${COMP_WORDS[COMP_CWORD]}).


Until recently, and as (possibly) fixed by
  
https://github.com/junegunn/fzf/commit/ee4ba104e722960376988e4e6971b5c5c271c643
it simply performed an `eval` on the current word (with the `**`
stripped off).

I've noticed that this may cause undesired side effects, e.g. when
trying to complete:
  $ ssh -i $(echo PWND > /tmp/FOO)**<TAB>
as described in:
  https://github.com/junegunn/fzf/issues/3459

The above commit does some heuristics to check whether any expansions
other than parameter expansion might get performed, and if so, it
simply doesn't do the `eval` and not perform any expansions.


I tried to analyse the fix as described in:
  https://github.com/junegunn/fzf/issues/3459#issuecomment-1744007338


points (1), (2) in the github comment linked above:

I'm especially not sure, whether it really catches all cases. I tried
really hard to trick it into executing something, but wasn't able to do
so.
However, I don't understand how bash splits that readline buffer to get
${COMP_WORDS[COMP_CWORD]}.

In especially, I would have assumed that the default of COMP_WORDBREAKS
protects against many of the cases of code injection, by containing the
characters used in bash's control operators.
So all that would be left needed, is excluding further cases like $(…)
and `…` (which the above patch does.

But AFAIU the bash manpage, it should be possible to change
COMP_WORDBREAKS (which a user might have done and which would cause the
fix to fail?)... but whenever I do that, completion stop from working
at al.


point (2) in the github comment linked above:
The "fix" by the above commit, also leaves at least one undesired side-
effect open, cause by ${parameter:=word}, which modifies `parameter`. 


point (6) in the github comment linked above:
The "fix" by the above commit, also causes false positives, where
expansion could be done but isn't.


points (4), (5) in the github comment linked above:
Discuss an which I don't understand either... could be a bug in bash-
completion, or maybe fzf simply wrongly uses the _ssh() function from
there.



Long story short:


Is there a proper/save way to expand any parameters in a command
string, without any side-effects (like from ${parameter:=word})?

That is especially: no execution of code via things like command or
process substitution or other tricky ways to inject code.


Actually I think there are two possible goals:
a) Either in a command string like:
     "${foo}" '$literal' "$(rm -rf /)"
   expand only the ${foo} and thus return something like:
     value_of_foo '$literal' "$(rm -rf /)"
   with the rm -rf / not being executed

b) Tell whether or not the command string contains anything that would
   possibly cause side effects.


I think for the purpose of fzf, (b) would actually be more helpful,
cause if in (a), the "$(rm -rf /)" remains (as code, but not to be
executed), fzf couldn't do anything useful with it anyway.


So the actual question is rather:

Can I tell whether a string that contains an arbitrary command to be
executed by eval, contains any expansions other than parameter
expansion (with the exception of the ${parameter:=word} form)... with
all quotings taken into account?



If the answer is now: "You need a shell parser"... than I guess we can
just forget about it, but maybe there's some simpler way :-)


Thanks,
Chris.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]