Skip to content

Document CRLF handling for http.server #142533

Closed

Description

@aydinnyunus

Bug report

Bug description:

Vulnerability Description

The send_header method in Lib/http/server.py writes headers directly to the output stream without checking for line breaks. When user-controlled input is passed to send_header, an attacker can inject CRLF sequences (\r\n) to terminate the current header and inject new headers or manipulate the response.

Vulnerable Code:

def send_header(self, keyword, value):
    """Send a MIME header to the headers buffer."""
    if self.request_version != 'HTTP/0.9':
        if not hasattr(self, '_headers_buffer'):
            self._headers_buffer = []
        self._headers_buffer.append(
            ("%s: %s\r\n" % (keyword, value)).encode('latin-1', 'strict'))
    # No validation for \r or \n characters!

Attack Scenarios

Scenario 1: Set-Cookie Injection (Session Fixation)

Vulnerable Application:

from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs, urlparse

class VulnerableHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        query = parse_qs(urlparse(self.path).query)
        custom_val = query.get('val', [''])[0]
        
        self.send_response(200)
        # VULNERABLE: Direct injection into header
        self.send_header('X-Custom', custom_val)
        self.end_headers()
        self.wfile.write(b"Hello World")

Attack URL:

http://localhost:8000/?val=test%0d%0aSet-Cookie:%20pwned=true

Result:

HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.x
Date: ...
X-Custom: test
Set-Cookie: pwned=true

Impact: Attacker can inject session cookies, leading to session fixation attacks.


Scenario 2: Location Header Injection (Malicious Redirect)

Attack URL:

http://localhost:8000/?val=test%0d%0ALocation:%20http://evil.com/

Result:

HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.x
Date: ...
X-Custom: test
Location: http://evil.com/

Impact:

  • Users are redirected to malicious websites
  • Phishing attacks
  • Open redirect vulnerabilities
  • Cache poisoning (if cached responses include the injected Location header)

Verified Test Results:

✓ LOCATION HEADER INJECTION CONFIRMED!
  Injected Location: http://evil.com/
✓ MALICIOUS REDIRECT CONFIRMED!
  Browser would redirect to: http://evil.com/
✓ MALICIOUS REDIRECT SUCCESSFUL!

Attack Vector

  • Type: Remote
  • Prerequisites:
    • Application uses http.server.BaseHTTPRequestHandler
    • User input is reflected in HTTP headers via send_header()
    • Common patterns: query parameters, user-agent reflection, custom headers
  • Complexity: Low - Simple URL manipulation
  • Authentication: Not required

Impact

  1. Session Fixation: Inject Set-Cookie headers to control user sessions
  2. Malicious Redirects: Inject Location headers to redirect users to attacker-controlled sites
  3. Cache Poisoning: Inject headers that affect cached responses
  4. Cross-Site Scripting (XSS): Inject headers that enable XSS attacks
  5. Web Cache Deception: Manipulate cache behavior via injected headers

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Activity

  1. added a commit that references this issue on Dec 12, 2025
  2. tadejmagajna commented on Dec 12, 2025

    @tadejmagajna
    Contributor

    @vadmium thanks for the suggestion about send_response_only. It’s now covered in the latest commit.

    The other cases from the linked issues are already handled in the PR by raising an exception, matching the approach you outlined. A review of the PR when you have time would be much appreciated.

  3. tadejmagajna commented on Dec 21, 2025

    @tadejmagajna
    Contributor

    @serhiy-storchaka, since you contributed to both http.server and wsgiref in the past, I was wondering if you might have the bandwidth to review this fix for the mentioned vulnerability.

  4. serhiy-storchaka commented on Dec 22, 2025

    @serhiy-storchaka
    Member

    http.server does not perform encoding (using QP or Base64) and line wrapping. Therefore, it is implied that the user is responsible for this -- it must pass an already encoded string, which can contain CRLF if the long string was folded. Isn't it?

  5. added 2 commits that reference this issue on Dec 27, 2025
  6. added
    docsDocumentation in the Doc dir
    and removed
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    pendingThe issue will be closed if no feedback is provided
    on Jan 3, 2026
  7. changed the title [-]CRLF Injection in http.server[/-] [+]Document CRLF handling for `http.server`[/+] on Jan 3, 2026
  8. added 3 commits that reference this issue on Jan 4, 2026
  9. aydinnyunus commented on Feb 4, 2026

    @aydinnyunus
    Author

    Hi team, I think document is not updated yet. Is there any deadline so I can close the issue 🙏

  10. picnixz commented on Feb 4, 2026

    @picnixz
    Member

    Do not close the issue, maintainers will take care of it when needed (in particular because there might have backports). I haven't time to read through it but I will try to do so this week-end (my daily job takes my time).

    EDIT: actually I already approved the PR. Victor was waiting for someone else if needed. I'll merge it this week-end then.

  11. added 3 commits that reference this issue on Apr 1, 2026
  12. added a commit that references this issue on Apr 2, 2026
  13. added 2 commits that reference this issue on Apr 2, 2026
  14. added 2 commits that reference this issue on Apr 2, 2026
  15. added a commit that references this issue on Apr 25, 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

    docsDocumentation in the Doc dir

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions