GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [CVE-2015-20107] mailcap.findmatch: document shell command Injection danger in filename parameter · Issue #68966 · python/cpython

[CVE-2015-20107] mailcap.findmatch: document shell command Injection danger in filename parameter #68966

New issue
Copy link
New issue
Copy link
Closed
Closed
[CVE-2015-20107] mailcap.findmatch: document shell command Injection danger in filename parameter#68966
Copy link
Labels
3.11only security fixesonly security fixesdocsDocumentation in the Doc dirDocumentation in the Doc dirstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-securityA security issueA security issue

Description

TheRegRunner
mannequin
opened on Aug 2, 2015
Issue body actions
BPO 24778
Nosy @vstinner, @bitdancer
Files
  • screenshot.png
  • The Quote Problem.py
  • mailcap patch.zip: mailcap.py patches and diffs for python2.7 and python 3.5
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2015-08-02.08:25:07.171>
    labels = ['type-security', '3.11', 'library', 'docs']
    title = 'mailcap.findmatch: document shell command Injection danger in filename parameter'
    updated_at = <Date 2022-04-06.15:30:37.106>
    user = 'https://bugs.python.org/TheRegRunner'

    bugs.python.org fields:

    activity = <Date 2022-04-06.15:30:37.106>
    actor = 'vstinner'
    assignee = 'docs@python'
    closed = False
    closed_date = None
    closer = None
    components = ['Documentation', 'Library (Lib)']
    creation = <Date 2015-08-02.08:25:07.171>
    creator = 'TheRegRunner'
    dependencies = []
    files = ['40099', '40116', '40897']
    hgrepos = []
    issue_num = 24778
    keywords = []
    message_count = 14.0
    messages = ['247857', '247861', '247944', '247946', '247951', '247979', '247992', '248058', '248061', '248062', '248070', '248074', '253689', '416878']
    nosy_count = 4.0
    nosy_names = ['vstinner', 'r.david.murray', 'docs@python', 'TheRegRunner']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'security'
    url = 'https://bugs.python.org/issue24778'
    versions = ['Python 3.11']

    Linked PRs

    • [3.9] gh-68966: fix versionchanged in docs #105298
    • [3.8] gh-68966: fix versionchanged in docs #105299
    • [3.7] gh-68966: fix versionchanged in docs #105300

    Activity

    Next
    1. TheRegRunner commented on Aug 2, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 2, 2015
      MannequinAuthor
      More actions

      if the filename contains Shell Commands they will be executed if they
      are passed to os.system() as discribed in the docs.
      Filename should be quoted with quote(filename) to fix the bug.

      https://docs.python.org/2/library/mailcap.html

      "mailcap.findmatch(/caps/, /MIMEtype/[, /key/[, /filename/[, /plist/]]])

      Return a 2-tuple; the first element is a string containing the
      command line to be executed
      (which can be passed to\*os.system() \*),
      

      ......"

      Exploid Demo wich runs xterm but should not :
      =============================

      import mailcap
      d=mailcap.getcaps()
      commandline,MIMEtype=mailcap.findmatch(d, "text/*", filename="'$(xterm);#.txt")
      ## commandline = "less ''$(xterm);#.txt'"
      import os
      os.system(commandline)
      ## xterm starts

      =============================

      By the way ... please do not use os.system() in your code, makes it unsafe.

      Best regards
      Bernd Dietzel
      Germany

    2. TheRegRunner
      added
      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
      type-securityA security issueA security issue
      on Aug 2, 2015
    3. TheRegRunner commented on Aug 2, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 2, 2015
      MannequinAuthor
      More actions

      Maybe it would be a good idea to do so as run-mailcap does :

      theregrunner@mint17 : ~ € run-mailcap --debug "';xterm;#'.txt"

      • parsing parameter "';xterm;#'.txt"
      • Reading mime.types file "/etc/mime.types"...
      • extension "txt" maps to mime-type "text/plain"
      • Reading mailcap file "/etc/mailcap"...
        Processing file "';xterm;#'.txt" of type "text/plain" (encoding=none)...
      • checking mailcap entry "text/plain; less '%s'; needsterminal"
      • program to execute: less '%s'
      • filename contains shell meta-characters; aliased to '/tmp/fileV7f2MZ'
      • executing: less '/tmp/fileV7f2MZ'
        theregrunner@mint17 : ~ €
    4. bitdancer commented on Aug 3, 2015

      @bitdancer
      bitdancer
      on Aug 3, 2015
      Member
      More actions

      In this case os.system is an appropriate API, because it mirrors the API of mailcap itself (that is, mailcap entries are shell commands).

      I'm not convinced there is a security bug here. It seems to me that there are two cases: either the filename is determined by the program, in which case there is no security issue, or the filename comes from an external source, and the program will have had to *write it to the file system* before the mailcap command will do anything. So the security hole, if any, will have happened earlier in the process.

      Now, one can argue that the quoting should be done in order to preserve the meaning of an arbitrary filename. Which would allay your concern even if I disagree that it is a real security bug :)

      (I don't understand why run-mailcap uses an alias rather than correctly quoting the meta-characters.)

    5. TheRegRunner commented on Aug 3, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 3, 2015
      MannequinAuthor
      More actions

      @david
      Thanks for the comment :-)

      I think if you read the Documentation
      https://docs.python.org/2/library/mailcap.html
      this may lead new programmers, wich may never heard of Shell Injections before, step by step directly to write insecure webbbrowsers and/or mail readers. At least there should be a warning in the docs !

      You ask why run-mailcap do not use quotig, i believe because quoting is not an easy thing to do, i attached a demo ;-)

      Thank you.

    6. TheRegRunner commented on Aug 3, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 3, 2015
      MannequinAuthor
      More actions

      Exploid Demo wich works with quote() :

      >>> commandline,MIMETYPE=mailcap.findmatch(d, 'text/*', filename=quote(';xterm;#.txt'))
      >>> commandline
      "less '';xterm;#.txt''"
      >>> os.system(commandline)
      ### xterm starts
      Reacted by VCbro
    7. bitdancer commented on Aug 4, 2015

      @bitdancer
      bitdancer
      on Aug 4, 2015
      Member
      More actions

      Hmm. I see. The problem is that our desire to quote conflicts with mailcap's attempts to quote.

      I now agree with you that run-mailcap's approach is correct, but creating a temporary alias is out of scope for findmatch. That would need to be done by findmatch's caller.

      I think we should add a documentation note about the problem and the solution. I don't see any reliable way to detect the problem and raise an error for the same reason that quoting doesn't work. (The aliasing can tolerate false positives; but, for backward compatibility reasons, an error detection function here cannot.)

      It would be possible to add a helper for the aliasing to 3.6, but if someone wants to propose that they should open an new issue for the enhancement.

      I'm

      Reacted by VCbro
    8. bitdancer
      added
      docsDocumentation in the Doc dirDocumentation in the Doc dir
      on Aug 4, 2015
    9. bitdancer
      assigned
      docspython
      on Aug 4, 2015
    10. TheRegRunner commented on Aug 4, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 4, 2015
      MannequinAuthor
      More actions

      Yes changing the docs is a good idea.

      I was thinking about a patch :

      import os
      ####### patch
      import random
      try:
        from shlex import quote
      except ImportError:
        from pipes import quote
      #######

      ....... and so on ....

      # Part 3: using the database.

      def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):
          """Find a match for a mailcap entry.
      Return a tuple containing the command line, and the mailcap entry
      used; (None, None) if no match is found.  This may invoke the
      'test' command of several matching entries before deciding which
      entry to use.
      
      """
      
          entries = lookup(caps, MIMEtype, key)
          # XXX This code should somehow check for the needsterminal flag.
          for e in entries:
              if 'test' in e:
                  test = subst(e['test'], filename, plist)
                  if test and os.system(test) != 0:
                      continue
      ####### patch
              ps=''.join(random.choice('python') for i in range(100))
              x=e[key]
              while '%s' in x:
                  x=x.replace('%s',ps)  
              command=subst(x, MIMEtype, filename, plist)
              while "'"+ps+"'" in command:
                  command=command.replace("'"+ps+"'",quote(filename))
              while ps in command:
                  command=command.replace(ps,quote(filename))          
      ######  command = subst(e[key], MIMEtype, filename, plist)
              return command, e
          return None, None
      Reacted by VCbro
    11. TheRegRunner commented on Aug 5, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 5, 2015
      MannequinAuthor
      More actions

      # for the docs ... quoting of the filename when you call mailcap.findmatch()

      f=";xterm;#.txt" # Shell Command Demo ... xterm will run if quote() fails

      import mailcap
      import random
      try:
        from shlex import quote
      except ImportError:
        from pipes import quote
      d=mailcap.getcaps()
      PY=''.join(random.choice('PYTHON') for i in range(100))
      cmd,MIMEtype=mailcap.findmatch(d, 'text/plain', filename=PY)
      while "'"+PY+"'" in cmd:
         cmd=cmd.replace("'"+PY+"'",quote(f))
      while PY in cmd:
         cmd=cmd.replace(PY,quote(f))
      print(cmd)  
      # less ';xterm;#.txt'
    12. bitdancer commented on Aug 5, 2015

      @bitdancer
      bitdancer
      on Aug 5, 2015
      Member
      More actions

      I have no idea what your code samples are trying to accomplish, I'm afraid, but that's not the kind of documentation I'm advocating anyway.

    13. bitdancer
      changed the title [-]mailcap.findmatch() ........ Shell Command Injection in filename[/-] [+]mailcap.findmatch: document shell command Injection danger in filename parameter[/+] on Aug 5, 2015
    14. TheRegRunner commented on Aug 5, 2015

      @TheRegRunner
      TheRegRunnermannequin
      on Aug 5, 2015
      MannequinAuthor
      More actions

      What i do is the last doc is like this :

      1. Replace the filename with a random name
      2. Run mailcap.findmatch() with the random name
      3. If exists, replace the quote characters ' before and behind the random name with nothing.
      4. Now the random name has no quoting from mailcap itself
      5. So now we can use our own quote() savely
    15. 100 remaining items

    16. stratakis
      added 2 commits that reference this issue on Mar 11, 2024

      00382: CVE-2015-20107

      573f018

      00382: CVE-2015-20107

      a9d260b
    17. stratakis
      added 5 commits that reference this issue on Mar 20, 2024

      00382: CVE-2015-20107

      4ecf0fb

      00382: CVE-2015-20107

      a557b3c

      00382: CVE-2015-20107

      5fd22d0

      00382: CVE-2015-20107

      273dac3

      00382: CVE-2015-20107

      c37c6c3
    18. hroncok
      added a commit that references this issue on Mar 26, 2024

      00382: CVE-2015-20107

      fbb090b
    19. mcepl
      added 3 commits that reference this issue on Apr 2, 2024

      00382: CVE-2015-20107

      6fe8c2d

      [CVE-2015-20107] Make mailcap refuse to match unsafe filenames/types/…

      d43fed4

      [CVE-2015-20107] Make mailcap refuse to match unsafe filenames/types/…

      ca268b2
    20. hrnciar
      added a commit that references this issue on Apr 23, 2025

      00382: CVE-2015-20107

      0e7b34b
    21. hroncok
      added a commit that references this issue on Jul 4, 2025

      00382: CVE-2015-20107

      0449071
    22. frenzymadness
      added a commit that references this issue on Aug 12, 2025

      00382: CVE-2015-20107

      f3931af
    23. hroncok
      added a commit that references this issue on Feb 3, 2026

      00382: CVE-2015-20107

      21a09fa
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.11only security fixesonly security fixesdocsDocumentation in the Doc dirDocumentation in the Doc dirstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-securityA security issueA security issue

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        You are visitor 01402503 — GeezerVison does not store the pages you look up.
        Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.