>Simple trick behind this technique is that when using shell wildcards, especially asterisk (...), Unix shell will interpret files beginning with hyphen (-) character as command line arguments to executed command/program.<p>To be clear, the shell isn't really 'interpreting' anything here — it knows absolutely nothing about the argument conventions of whatever program you're running[0]. All it's doing is passing a list of arguments to an executable; how the executable deals with that is up to it.<p>And this isn't only a shell problem — it's an issue when you pass arbitrary arguments to ANY external utility in ANY language. For example, maybe you have some kind of tool that calls grep:<p><pre><code> # Perl
exec '/usr/bin/grep', '-R', $input, 'mydir';
# PHP (with Symfony Process)
(new Process(['/usr/bin/grep', '-R', $input, 'mydir']))->run();
# Python
subprocess.run(['/usr/bin/grep', '-R', input, 'mydir'])
# C
execv("/usr/bin/grep", (char *[]) {"grep", "-R", input, "mydir", NULL});
</code></pre>
All of these are safe in the sense that there's no risk of shell command injection (in fact, only the PHP one even calls the shell), but NONE of them are safe against this problem, where the input value might begin with a hyphen. In this grep scenario it's probably not a security issue, but it can produce confusing results for the user if nothing else.<p>As others mentioned, you must ALWAYS use '--' to mark the end of option processing when you do something like this.<p>[0] Technically the shell knows about the conventions of its built-ins, but even those mostly handle arguments in a similar fashion to external utilities, where an arbitrary argv is fed to a function and then parsed using some getopts-like method.