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 — Security hole in wsgiref.headers.Headers · Issue #55880 · python/cpython

Security hole in wsgiref.headers.Headers #55880

New issue
Copy link
New issue
Copy link
Closed
Closed
Security hole in wsgiref.headers.Headers#55880
Copy link
Labels
3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-securityA security issueA security issue

Description

FelixGrbert
mannequin
opened on Mar 25, 2011
Issue body actions
BPO 11671
Nosy @pjeby, @vstinner, @tiran, @vadmium, @epicfaace
PRs
  • bpo-11671: add header validation from http.client to wsgiref.headers.Headers #15299
  • Files
  • header_newlines_tip.patch
  • 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 2011-03-25.12:14:57.540>
    labels = ['type-security', '3.8', '3.7', 'library', '3.9']
    title = 'Security hole in wsgiref.headers.Headers'
    updated_at = <Date 2019-08-15.04:22:13.409>
    user = 'https://bugs.python.org/FelixGrbert'

    bugs.python.org fields:

    activity = <Date 2019-08-15.04:22:13.409>
    actor = 'epicfaace'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2011-03-25.12:14:57.540>
    creator = 'Felix.Gr\xc3\xb6bert'
    dependencies = []
    files = ['29238']
    hgrepos = []
    issue_num = 11671
    keywords = ['patch']
    message_count = 10.0
    messages = ['132080', '132132', '132393', '182766', '182781', '182782', '182973', '182976', '195487', '195491']
    nosy_count = 8.0
    nosy_names = ['pje', 'vstinner', 'christian.heimes', 'Arfrever', 'devin', 'Felix.Gr\xc3\xb6bert', 'martin.panter', 'epicfaace']
    pr_nums = ['15299']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'security'
    url = 'https://bugs.python.org/issue11671'
    versions = ['Python 2.7', 'Python 3.5', 'Python 3.6', 'Python 3.7', 'Python 3.8', 'Python 3.9']

    Activity

    1. FelixGrbert commented on Mar 25, 2011

      @FelixGrbert
      FelixGrbertmannequin
      on Mar 25, 2011
      MannequinAuthor
      More actions

      As noted by [email protected]'s response I'm filing this bug here.

      In wsgiref.headers.Headers it is possible to include headers which
      contain a newline (i.e. \n or \r) either through add_header or
      __init__. It is not uncommon that developers provide web applications
      to the public in which the HTTP response headers are not filtered for
      newlines but are controlled by the user. In such scenarios a malicious
      user can use a newline to inject another header or even initiate a
      HTTP response body. The impact would be at least equivalent to XSS.
      Therefore, I suggest to filter/warn/except header tuples which contain
      the above characters upon assignment in wsgiref.headers.

    2. FelixGrbert
      added
      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
      type-securityA security issueA security issue
      on Mar 25, 2011
    3. merwok
      assigned
      pjeby
      on Mar 25, 2011
    4. merwok
      changed the title [-]Potential misuse of wsgiref.headers.Headers[/-] [+]Security hole in wsgiref.headers.Headers[/+] on Mar 25, 2011
    5. pjeby commented on Mar 25, 2011

      @pjeby
      pjebymannequin
      on Mar 25, 2011
      Mannequin
      More actions

      It is not uncommon that developers provide web applications
      to the public in which the HTTP response headers are not filtered for
      newlines but are controlled by the user.

      Really? Which applications, and which response headers?

      Therefore, I suggest to filter/warn/except header tuples which contain
      the above characters upon assignment in wsgiref.headers.

      Applications that send them are not WSGI compliant anyway, since the spec forbids control characters in header strings -- and wsgiref.validate already validates this.

      Still, I'm not aware of any legitimate use case for apps sending user input as an HTTP header where the data wouldn't already be escaped in some fashion -- cookies, URLs, ...?

    6. FelixGrbert commented on Mar 28, 2011

      @FelixGrbert
      FelixGrbertmannequin
      on Mar 28, 2011
      MannequinAuthor
      More actions

      If the spec forbids control characters in headers, the module should
      enforce that.

      The most frequent example of header injection is the redirect-case: an
      application is forwarding using the Location header to a user-supplied
      URL.
      http://google.com/codesearch?as_q=self.redirect%5C%28self.request.get
      Other examples are proxies, setting user-agent, or, as you mention,
      custom set-cookies headers.

    7. devin commented on Feb 23, 2013

      @devin
      devinmannequin
      on Feb 23, 2013
      Mannequin
      More actions

      Should now be compliant with this part of the spec:

      "Each header_value must not include any control characters, including carriage returns or linefeeds, either embedded or at the end. (These requirements are to minimize the complexity of any parsing that must be performed by servers, gateways, and intermediate response processors that need to inspect or modify response headers.)"

    8. devin commented on Feb 23, 2013

      @devin
      devinmannequin
      on Feb 23, 2013
      Mannequin
      More actions

      backported patch to 2.7

    9. devin commented on Feb 23, 2013

      @devin
      devinmannequin
      on Feb 23, 2013
      Mannequin
      More actions

      backported patch to 2.6

    10. vstinner commented on Feb 25, 2013

      @vstinner
      vstinner
      on Feb 25, 2013
      Member
      More actions

      + if bad_header_value_re.search(_value):
      + error_str = "Bad header value: {0!r} (bad char: {1!r})"
      + raise AssertionError(error_str.format(
      + _value, bad_header_value_re.search(_value).group(0)))

      Why do you search the character twice? You can do something like:

      match = bad_header_value_re.search(_value)
      if match is not None:
        ... match..group(0) ...

      Why do you only check value? You should also check _params:

      parts = "; ".join(parts)
      match = bad_header_value_re.search(parts)
      ...

      And you should also check the name.

      Should we do the same checks in httplib?

    11. devin commented on Feb 25, 2013

      @devin
      devinmannequin
      on Feb 25, 2013
      Mannequin
      More actions

      The spec doesn't say anything about the header name. It probably should though, as the same issue exists there.

      I used two searches because that's how it's done in wsgiref.validate, and it's not a huge deal to do that because the second one will only execute when there's an error. That said, I changed it to how you proposed.

      Here's another stab at that patch.

    12. tiran commented on Aug 17, 2013

      @tiran
      tiran
      on Aug 17, 2013
      Member
      More actions

      What do the RFCs for RFC-822 and HTTP 1.1 say about \r and \n in header names?

    13. devin commented on Aug 17, 2013

      @devin
      devinmannequin
      on Aug 17, 2013
      Mannequin
      More actions

      It looks like it's allowed for header line continuation.

      http://www.ietf.org/rfc/rfc2616.txt

      HTTP/1.1 header field values can be folded onto multiple lines if the
      continuation line begins with a space or horizontal tab. All linear
      white space, including folding, has the same semantics as SP. A
      recipient MAY replace any linear white space with a single SP before
      interpreting the field value or forwarding the message downstream.

      ...

      A CRLF is allowed in the definition of TEXT only as part of a header
      field continuation. It is expected that the folding LWS will be
      replaced with a single SP before interpretation of the TEXT value.

    14. tiran
      added
      3.7 (EOL)end of lifeend of life
      on Sep 8, 2016
    15. tiran
      unassigned
      pjeby
      on Sep 8, 2016
    16. epicfaace
      added
      3.8 (EOL)end of lifeend of life
      3.9 (EOL)end of lifeend of life
      on Aug 15, 2019
    17. ezio-melotti
      transferred this issue fromon Apr 10, 2022
    18. sethmlarson commented on Mar 10, 2026

      @sethmlarson
      sethmlarson
      on Mar 10, 2026
      Contributor
      More actions

      Closed by #143917

    19. sethmlarson
      closed this as completedon Mar 10, 2026
    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.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard 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 01402520 — 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.