#36931: Unhandled LookupError in multipart parser when RFC 2231 encoding name is
invalid
-------------------------------------+-------------------------------------
     Reporter:  sammiee5311          |                     Type:  Bug
       Status:  new                  |                Component:  HTTP
                                     |  handling
      Version:  6.0                  |                 Severity:  Normal
     Keywords:  multipart parser     |             Triage Stage:
  LookupError RFC2231                |  Unreviewed
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  1                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 When a multipart form upload includes an RFC 2231 encoded `filename*`
 parameter with an invalid encoding name (e.g.,
 `filename*=BOGUS''test%20file.txt`),
 
[parse_header_parameters()](https://github.com/django/django/blob/main/django/utils/http.py#L332),
 
[django/utils/http.py](https://github.com/django/django/blob/main/django/utils/http.py)
 passes the encoding to `urllib.parse.unquote()`, which raises
 `LookupError`.

 The caller in
 
[django/http/multipartparser.py](https://github.com/django/django/blob/main/django/http/multipartparser.py#L729)
 only catches `ValueError`:

 {{{#!python
 except ValueError:  # Invalid header.
     continue
 }}}

 Since `LookupError` is not a subclass of `ValueError`, the exception
 propagates and results in a 500 Internal Server Error.


 == Steps to Reproduce ==
 1. Create a simple upload view:
 {{{#!python
 from django.http import JsonResponse
 from django.views.decorators.csrf import csrf_exempt
 @csrf_exempt
 def upload(request):
     if request.method == "POST" and request.FILES:
         return JsonResponse({"filename": request.FILES["file"].name})
     return JsonResponse({"error": "No file"}, status=400)
 }}}
 2. Send a multipart request with a bogus encoding:
 {{{#!python
 import http.client
 boundary = "----PoC"
 body = (
     f"--{boundary}\r\n"
     f"Content-Disposition: form-data; name=\"file\"; "
     f"filename*=BOGUS''test%20file.txt\r\n"
     f"Content-Type: application/octet-stream\r\n"
     f"\r\n"
     f"content\r\n"
     f"--{boundary}--\r\n"
 )
 conn = http.client.HTTPConnection("localhost", 8000)
 conn.request("POST", "/upload/", body=body.encode(),
     headers={"Content-Type": f"multipart/form-data; boundary={boundary}"})
 print(conn.getresponse().status)  # Returns 500
 }}}

 The filename must contain at least one percent-encoded character (e.g.,
 `%20`) for `unquote()` to invoke the codec.

 Confirmed on Django 6.0.2, Python 3.14.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36931>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019c647529fe-afdf1257-4b9a-41b3-a24d-c8fc0f0fd700-000000%40eu-central-1.amazonses.com.

Reply via email to