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