{"id":"1aa98f9eb00ca4f1","repo":"aio-libs/aiohttp","slug":"invalid-default-charset","errorCode":null,"errorMessage":"Invalid default charset","messagePattern":"Invalid default charset","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":771,"sourceCode":"            await self._read_boundary()\n        if self._at_eof:  # we just read the last boundary, nothing to do there\n            # https://github.com/python/mypy/issues/17537\n            return None  # type: ignore[unreachable]\n\n        part = await self.fetch_next_part()\n        # https://datatracker.ietf.org/doc/html/rfc7578#section-4.6\n        if (\n            self._last_part is None\n            and self._mimetype.subtype == \"form-data\"\n            and isinstance(part, BodyPartReader)\n        ):\n            _, params = parse_content_disposition(part.headers.get(CONTENT_DISPOSITION))\n            if params.get(\"name\") == \"_charset_\":\n                # Longest encoding in https://encoding.spec.whatwg.org/encodings.json\n                # is 19 characters, so 32 should be more than enough for any valid encoding.\n                charset = await part.read_chunk(32)\n                if len(charset) > 31:\n                    raise RuntimeError(\"Invalid default charset\")\n                self._default_charset = charset.strip().decode()\n                part = await self.fetch_next_part()\n        self._last_part = part\n        return self._last_part\n\n    async def release(self) -> None:\n        \"\"\"Reads all the body parts to the void till the final boundary.\"\"\"\n        while not self._at_eof:\n            item = await self.next()\n            if item is None:\n                break\n            await item.release()\n\n    async def fetch_next_part(\n        self,\n    ) -> Union[\"MultipartReader\", BodyPartReader]:\n        \"\"\"Returns the next body part reader.\"\"\"\n        headers = await self._read_headers()","sourceCodeStart":753,"sourceCodeEnd":789,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/multipart.py#L753-L789","documentation":"Raised by MultipartReader.next() when processing a multipart/form-data body that uses the _charset_ convention (RFC 7578 §4.6): the first part named '_charset_' declares the default charset for subsequent parts. aiohttp reads up to 32 bytes for that value; if more than 31 bytes are read it treats the charset as invalid/malicious and raises RuntimeError.","triggerScenarios":"Receiving a multipart/form-data request whose first part is named '_charset_' but whose body is longer than 31 bytes. This is almost always malformed or malicious input, since real charset names are short (longest in the WHATWG list is ~19 chars).","commonSituations":"Fuzzing/malicious clients; a buggy form generator that puts the wrong content into the _charset_ field; a client confusing the _charset_ field with an actual text value.","solutions":["Reject the request with 400 — a >31-byte _charset_ value is not legitimate.","Fix the client so the _charset_ part contains a real, short encoding name (e.g. 'utf-8').","Wrap multipart parsing in try/except RuntimeError and treat it as a bad request."],"exampleFix":"// before\nasync for part in request.multipart():  # _charset_ too long -> RuntimeError\n    ...\n// after\ntry:\n    async for part in request.multipart():\n        ...\nexcept RuntimeError:\n    return web.Response(status=400, text='malformed multipart form')\n","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    async for part in request.multipart():\n        process(part)\nexcept RuntimeError as e:\n    if 'Invalid default charset' in str(e):\n        return web.Response(status=400, text='malformed _charset_ field')\n    raise","preventionTips":["Treat multipart parsing failures as 400 by default.","Log _charset_ values during incidents to spot malicious clients.","Rate-limit multipart endpoints to blunt header/charset bombs."],"tags":["multipart","form-data","charset","validation","security"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}