Skip to content

rewrite CGIHTTPRequestHandler to always use subprocess #61149

Closed as not planned
Closed as not planned

Description

@neologix
mannequin
BPO 16945
Nosy @orsenthil, @pitrou
Dependencies
  • bpo-10496: Python startup should not require passwd entry
  • Files
  • cgi_subprocess.diff
  • cgi_subprocess-1.diff
  • 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 2013-01-12.14:14:43.430>
    labels = ['type-bug']
    title = 'rewrite CGIHTTPRequestHandler to always use subprocess'
    updated_at = <Date 2013-08-02.06:56:00.467>
    user = 'https://bugs.python.org/neologix'

    bugs.python.org fields:

    activity = <Date 2013-08-02.06:56:00.467>
    actor = 'neologix'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = []
    creation = <Date 2013-01-12.14:14:43.430>
    creator = 'neologix'
    dependencies = ['10496']
    files = ['28706', '29219']
    hgrepos = []
    issue_num = 16945
    keywords = ['patch', 'needs review']
    message_count = 3.0
    messages = ['179797', '188359', '194158']
    nosy_count = 4.0
    nosy_names = ['orsenthil', 'pitrou', 'v+python', 'neologix']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue16945'
    versions = ['Python 3.4']

    Activity

    1. neologix commented on Jan 12, 2013

      neologixmannequin
      MannequinAuthor

      On Unix, CGIHTTPRequestHandler.run_cgi() uses the following code to run a CGI script:
      """
      pid = os.fork()
      [...]
      # Child
      try:
      try:
      os.setuid(nobody)
      except OSError:
      pass
      os.dup2(self.rfile.fileno(), 0)
      os.dup2(self.wfile.fileno(), 1)
      os.execve(scriptfile, args, env)
      """

      It's basically reimplementing subprocess.Popen, with a potential securiy issue: open file descriptors are not closed before exec, which means that the CGI script - which is run as 'nobody' on Unix to reduce its priviledges - can inherit open sockets or files (unless they're close-on-exec)...

      The attached patch rewrites run_cgi() to use subprocess on all platorms.
      I'm not at all familiar with CGI, so I don't guarantee it's correct, but the regression test test_httpservers passes on Linux.

      It leads to cleaner and safer code, so if someone with some httpsever/CGI background could review it, it would be great.

    2. neologix commented on May 4, 2013

      neologixmannequin
      MannequinAuthor

      The latest version of the patch passes on Linux, OpenIndiana and Windows.

      Note that I did apply the select()-hack on all platforms (not only Windows), because if I understood bpo-427345 correctly, it's really there to bypass a non-standard IE behavior (which appends trailing '\r\n'), and doesn't depend on the platform.

    3. neologix commented on Aug 2, 2013

      neologixmannequin
      MannequinAuthor

      Marking bpo-10496 as a dependency (since it could prevent Python from running with low level privileges).

    4. transferred this issue fromon Apr 10, 2022
    5. added
      stdlibStandard Library Python modules in the Lib/ directory
      on Nov 27, 2023
    6. added
      3.11only security fixes
      3.12only security fixes
      3.13only security fixes
      3.14bugs and security fixes
      on Sep 17, 2025
    7. devdanzin commented on Sep 17, 2025

      @devdanzin
      Member

      Since CGIHTTPRequestHandler is being removed in 3.15, I think this should be closed. However, the author mentions a security issue with the current code, making it a possible bug fix we still want to land.

    8. picnixz commented on Sep 17, 2025

      @picnixz
      Member

      CGI is already a bad thing when it comes to security, see the note https://docs.python.org/3.12/library/cgi.html#caring-about-security:

      There’s one important rule: if you invoke an external program (via os.system(), os.popen() or other functions with similar functionality), make very sure you don’t pass arbitrary strings received from the client to the shell. This is a well-known security hole whereby clever hackers anywhere on the web can exploit a gullible CGI script to invoke arbitrary shell commands. Even parts of the URL or field names cannot be trusted, since the request doesn’t have to come from your form!

      This note is for the CGI module that was already removed. Now, for the handler, we're already in the a test server module which says:

      http.server is not recommended for production. It only implements basic security checks.

      I don't think it's worth fixing 3.9 to 3.14 as we'll eventually throw away this kind of code. I however agree that the open file descriptors are inherited by the CGI script but I think it's more a "non-security-issue" here. Indeed, expecting Python to execute a CGI script also means expecting the script to be trusted (we don't guarantee that we would protect the user against malicious scripts; in addition, we already warn the user by saying we implement basic security checks).

      I will take the blame if something should happen so I'll close this issue as "wont fix". If you're concerned with security, don't use CGI and don't use http.server which is not meant for production use.

    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.10 (EOL)end of life3.11only security fixes3.12only security fixes3.13only security fixes3.14bugs and security fixes3.9 (EOL)end of lifestdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errortype-securityA security issue

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions