diff -r 68f263f52d2e -r 77eaf9539499 mercurial/dispatch.py --- a/mercurial/dispatch.py Mon Apr 03 17:34:24 2017 -0400 +++ b/mercurial/dispatch.py Wed Apr 12 11:23:55 2017 -0700 @@ -155,6 +155,37 @@ pass # happens if called in a thread def _runcatchfunc(): + realcmd = None + try: + cmdargs = fancyopts.fancyopts(req.args[:], commands.globalopts, {}) + cmd = cmdargs[0] + aliases, entry = cmdutil.findcmd(cmd, commands.table, False) + realcmd = aliases[0] + except (error.UnknownCommand, error.AmbiguousCommand, + IndexError, getopt.GetoptError): + # Don't handle this here. We know the command is + # invalid, but all we're worried about for now is that + # it's not a command that server operators expect to + # be safe to offer to users in a sandbox. + pass + if realcmd == 'serve' and '--stdio' in cmdargs: + # We want to constrain 'hg serve --stdio' instances pretty + # closely, as many shared-ssh access tools want to grant + # access to run *only* 'hg -R $repo serve --stdio'. We + # restrict to exactly that set of arguments, and prohibit + # any repo name that starts with '--' to prevent + # shenanigans wherein a user does something like pass + # --debugger or --config=ui.debugger=1 as a repo + # name. This used to actually run the debugger. + if (len(req.args) != 4 or + req.args[0] != '-R' or + req.args[1].startswith('--') or + req.args[2] != 'serve' or + req.args[3] != '--stdio'): + raise error.Abort( + _('potentially unsafe serve --stdio invocation: %r') % + (req.args,)) + try: debugger = 'pdb' debugtrace = {