|
150 | 150 | # _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$") |
151 | 151 | # We are more lenient for assumed real world compatibility purposes. |
152 | 152 |
|
| 153 | +# These characters are not allowed within HTTP method names |
| 154 | +# to prevent http header injection. |
| 155 | +_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]') |
| 156 | + |
153 | 157 | # We always set the Content-Length header for these methods because some |
154 | 158 | # servers will otherwise respond with a 411 |
155 | 159 | _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} |
@@ -1109,6 +1113,8 @@ def putrequest(self, method, url, skip_host=False, |
1109 | 1113 | else: |
1110 | 1114 | raise CannotSendRequest(self.__state) |
1111 | 1115 |
|
| 1116 | + self._validate_method(method) |
| 1117 | + |
1112 | 1118 | # Save the method for use later in the response phase |
1113 | 1119 | self._method = method |
1114 | 1120 |
|
@@ -1199,6 +1205,15 @@ def _encode_request(self, request): |
1199 | 1205 | # ASCII also helps prevent CVE-2019-9740. |
1200 | 1206 | return request.encode('ascii') |
1201 | 1207 |
|
| 1208 | + def _validate_method(self, method): |
| 1209 | + """Validate a method name for putrequest.""" |
| 1210 | + # prevent http header injection |
| 1211 | + match = _contains_disallowed_method_pchar_re.search(method) |
| 1212 | + if match: |
| 1213 | + raise ValueError( |
| 1214 | + f"method can't contain control characters. {method!r} " |
| 1215 | + f"(found at least {match.group()!r})") |
| 1216 | + |
1202 | 1217 | def _validate_path(self, url): |
1203 | 1218 | """Validate a url for putrequest.""" |
1204 | 1219 | # Prevent CVE-2019-9740. |
|
0 commit comments