The shipped script less-osc8-open.sh is registered as the default value of LESS_OSC8_OPEN_ANY in decode.c:
static char dflt_vartable[] =
{
"LESS_OSC8_OPEN_ANY\0\201"
#ifdef LIBEXECDIR
"-" LIBEXECDIR "/less-osc8-open"
#else
"-less-osc8-open"
#endif
"\0"
};
When the user activates an OSC 8 hyperlink (Ctrl-O Ctrl-O, or a second mouse click in mouse mode), osc8_open() in search.c invokes the handler with the URI as a single shell-quoted argument:
uri_q = shell_quoten(op.uri_start, uri_len);
cmd = ecalloc(strlen(handler) + strlen(uri_q) + 2, sizeof(char));
sprintf(cmd, "%s %s", handler, uri_q);
...
lsystem(exec_cmd, done_msg);
That delivers the URI verbatim into the script as $1. Inside the script, the man:NAME(SECTION) case splits the URI:
case $1 in
man:?*\(*\) )
sect=${1#*\(}; sect=${sect%?}
name=${1#man:}; name=${name%%\(*}
man ${sect:+"$sect"} "$name"
;;
${sect:+"$sect"} expands to a single argv word, but man still interprets a word beginning with - as an option. Both GNU man-db and BSD man accept -P pager/-Ppager/--pager=pager with shell-tokenised pager strings, and man-db documents that the value "may be a simple command name or a command with arguments." Tokenisation alone is sufficient for execution: the pager argv is execvp'd with man's formatted output on stdin.
Reproduction
URI inside OSC 8 sequence: man:ls(-P /usr/bin/touch /tmp/pwn)
OSC 8 wire form: \x1b]8;;man:ls(-P /usr/bin/touch /tmp/pwn)\x1b\\click here\x1b]8;;\x1b\\
The shipped script
less-osc8-open.shis registered as the default value ofLESS_OSC8_OPEN_ANYindecode.c:When the user activates an OSC 8 hyperlink (Ctrl-O Ctrl-O, or a second mouse click in mouse mode),
osc8_open()insearch.cinvokes the handler with the URI as a single shell-quoted argument:That delivers the URI verbatim into the script as
$1. Inside the script, theman:NAME(SECTION)case splits the URI:${sect:+"$sect"}expands to a single argv word, butmanstill interprets a word beginning with-as an option. Both GNUman-dband BSDmanaccept-P pager/-Ppager/--pager=pagerwith shell-tokenised pager strings, andman-dbdocuments that the value "may be a simple command name or a command with arguments." Tokenisation alone is sufficient for execution: the pager argv isexecvp'd with man's formatted output on stdin.Reproduction