{"record":{"id":"49c689896da5eeb8","repo":"aio-libs/aiohttp","slug":"bad-http-method-in-status-line-method-r","errorCode":null,"errorMessage":"Bad HTTP method in status line {method!r}","messagePattern":"Bad HTTP method in status line (.+?)","errorType":"exception","errorClass":"BadHttpMethod","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":665,"sourceCode":"class HttpRequestParser(HttpParser[RawRequestMessage]):\n    \"\"\"Read request status line.\n\n    Exception .http_exceptions.BadStatusLine\n    could be raised in case of any errors in status line.\n    Returns RawRequestMessage.\n    \"\"\"\n\n    def parse_message(self, lines: list[bytes]) -> RawRequestMessage:\n        # request line\n        line = lines[0].decode(\"utf-8\", \"surrogateescape\")\n        try:\n            method, path, version = line.split(\" \", maxsplit=2)\n        except ValueError:\n            raise BadHttpMethod(line) from None\n\n        # method\n        if not TOKENRE.fullmatch(method):\n            raise BadHttpMethod(method)\n        method = method.upper()\n\n        # version\n        match = VERSRE.fullmatch(version)\n        if match is None:\n            raise BadStatusLine(line)\n        version_o = HttpVersion(int(match.group(1)), int(match.group(2)))\n\n        if method == \"CONNECT\":\n            # authority-form,\n            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3\n            url = URL.build(authority=path, encoded=True)\n        elif path.startswith(\"/\"):\n            # origin-form,\n            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1\n            path_part, _hash_separator, url_fragment = path.partition(\"#\")\n            path_part, _question_mark_separator, qs_part = path_part.partition(\"?\")\n","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L647-L683","documentation":"Raised when the method token does not fully match TOKENRE [0-9A-Za-z!#$%&'*+-.^_`|~]+. Methods must be RFC 9110 tokens: no spaces, no control bytes, no delimiters.","triggerScenarios":"A method containing any non-token character: 'GE/T', 'GET\\r' (CRLF injection), an empty method, or a custom method with delimiters.","commonSituations":"Custom clients sending malformed methods, CRLF-injection attacks, fuzzing, encoding bugs.","solutions":["Send a standard method token (GET, POST, ...).","Validate custom methods against the token charset before sending.","Reject malformed methods at the edge."],"exampleFix":"# before\nsock.send(b'G@T / HTTP/1.1\\r\\n')\n\n# after\nsock.send(b'GET / HTTP/1.1\\r\\n')","handlingStrategy":"validation","validationCode":"import re\n_TOKEN = re.compile(r\"[0-9A-Za-z!#$%&'*+-.^_`|~]+\")\ndef safe_method(m: str) -> str | None:\n    return m if _TOKEN.fullmatch(m) else None","typeGuard":"import re\n_TOKEN = re.compile(r\"[0-9A-Za-z!#$%&'*+-.^_`|~]+\")\ndef is_method_token(m: str) -> bool:\n    return bool(_TOKEN.fullmatch(m))","tryCatchPattern":"from aiohttp.http_exceptions import BadHttpMethod\ntry:\n    ...parse...\nexcept BadHttpMethod as e:\n    transport.close()","preventionTips":["Treat the method as a token; never allow user-controlled delimiters in it.","When accepting custom methods, validate them against TOKENRE first."],"tags":["http","parser","request-line","method","security","validation"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}