{"record":{"id":"1880818c3e2a2de5","repo":"aio-libs/aiohttp","slug":"boundary-r-is-too-long-70-chars-max","errorCode":null,"errorMessage":"boundary %r is too long (70 chars max)","messagePattern":"boundary %r is too long \\(70 chars max\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":841,"sourceCode":"                max_field_size=self._max_field_size,\n                max_headers=self._max_headers,\n                max_size_error_cls=self._max_size_error_cls,\n            )\n        else:\n            return self.part_reader_cls(\n                self._boundary,\n                headers,\n                self._content,\n                subtype=self._mimetype.subtype,\n                default_charset=self._default_charset,\n                client_max_size=self._client_max_size,\n                max_size_error_cls=self._max_size_error_cls,\n            )\n\n    def _get_boundary(self) -> str:\n        boundary = self._mimetype.parameters[\"boundary\"]\n        if len(boundary) > 70:\n            raise ValueError(\"boundary %r is too long (70 chars max)\" % boundary)\n\n        return boundary\n\n    async def _readline(self) -> bytes:\n        if self._unread:\n            return self._unread.pop()\n        return await self._content.readline()\n\n    async def _read_until_first_boundary(self) -> None:\n        while True:\n            chunk = await self._readline()\n            if chunk == b\"\":\n                raise ValueError(f\"Could not find starting boundary {self._boundary!r}\")\n            chunk = chunk.rstrip()\n            if chunk == self._boundary:\n                return\n            elif chunk == self._boundary + b\"--\":\n                self._at_eof = True","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/multipart.py#L823-L859","documentation":"MultipartReader._get_boundary enforces the RFC 2046 limit of 70 characters on the boundary parameter. If the boundary string from the Content-Type exceeds 70 chars, ValueError is raised before any reading begins.","triggerScenarios":"A Content-Type header whose boundary= value is longer than 70 characters; typically a misconfigured or adversarial sender.","commonSituations":"Producers generating boundaries from long UUIDs concatenated with extra prefixes/suffixes; copy-paste of base64 blobs as boundary; fuzzing.","solutions":["Shorten the boundary value to <= 70 characters (RFC 2046 allows up to 70).","Use the boundary produced by MultipartWriter on the producing side, which respects the limit.","Validate Content-Type boundary length on the server and return 400 before constructing the reader.","Catch ValueError and reject the request as malformed."],"exampleFix":"// before\nContent-Type: multipart/form-data; boundary=AAAAAAAAAA...70+chars...AAAAA\n\n// after\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxk","handlingStrategy":"validation","validationCode":"MAX_BOUNDARY = 70\n\ndef assert_boundary_length(content_type: str) -> None:\n    mt = parse_mimetype(content_type)\n    b = mt.parameters.get('boundary')\n    if mt.type == 'multipart' and (not b or len(b) > MAX_BOUNDARY):\n        raise ValueError(f'boundary missing or too long (> {MAX_BOUNDARY})')","typeGuard":"def is_valid_boundary_length(content_type: object) -> bool:\n    if not isinstance(content_type, str):\n        return False\n    mt = parse_mimetype(content_type)\n    b = mt.parameters.get('boundary')\n    return mt.type != 'multipart' or bool(b) and len(b) <= 70","tryCatchPattern":"try:\n    reader = MultipartReader(headers, content)\nexcept ValueError as e:\n    if 'too long' in str(e):\n        return web.Response(status=400, text='Boundary exceeds 70 characters')\n    raise","preventionTips":["Keep boundary tokens <= 70 characters (30-50 is comfortable).","Validate the Content-Type boundary length server-side before parsing.","Use a producer that respects the RFC 2046 limit (MultipartWriter does)."],"tags":["multipart","boundary","validation","rfc-2046","input-validation"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}