|
151 | 151 | # _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$") |
152 | 152 | # We are more lenient for assumed real world compatibility purposes. |
153 | 153 |
|
| 154 | +# These characters are not allowed within HTTP method names |
| 155 | +# to prevent http header injection. |
| 156 | +_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]') |
| 157 | + |
154 | 158 | # We always set the Content-Length header for these methods because some |
155 | 159 | # servers will otherwise respond with a 411 |
156 | 160 | _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} |
@@ -985,6 +989,8 @@ def putrequest(self, method, url, skip_host=False, |
985 | 989 | else: |
986 | 990 | raise CannotSendRequest(self.__state) |
987 | 991 |
|
| 992 | + self._validate_method(method) |
| 993 | + |
988 | 994 | # Save the method for use later in the response phase |
989 | 995 | self._method = method |
990 | 996 |
|
@@ -1075,6 +1081,16 @@ def _encode_request(self, request): |
1075 | 1081 | # ASCII also helps prevent CVE-2019-9740. |
1076 | 1082 | return request.encode('ascii') |
1077 | 1083 |
|
| 1084 | + def _validate_method(self, method): |
| 1085 | + """Validate a method name for putrequest.""" |
| 1086 | + # prevent http header injection |
| 1087 | + match = _contains_disallowed_method_pchar_re.search(method) |
| 1088 | + if match: |
| 1089 | + raise ValueError( |
| 1090 | + "method can't contain control characters. %r " |
| 1091 | + "(found at least %r)" |
| 1092 | + % (method, match.group())) |
| 1093 | + |
1078 | 1094 | def _validate_path(self, url): |
1079 | 1095 | """Validate a url for putrequest.""" |
1080 | 1096 | # Prevent CVE-2019-9740. |
|
0 commit comments