|
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'} |
@@ -1087,6 +1091,8 @@ def putrequest(self, method, url, skip_host=False, |
1087 | 1091 | else: |
1088 | 1092 | raise CannotSendRequest(self.__state) |
1089 | 1093 |
|
| 1094 | + self._validate_method(method) |
| 1095 | + |
1090 | 1096 | # Save the method for use later in the response phase |
1091 | 1097 | self._method = method |
1092 | 1098 |
|
@@ -1177,6 +1183,15 @@ def _encode_request(self, request): |
1177 | 1183 | # ASCII also helps prevent CVE-2019-9740. |
1178 | 1184 | return request.encode('ascii') |
1179 | 1185 |
|
| 1186 | + def _validate_method(self, method): |
| 1187 | + """Validate a method name for putrequest.""" |
| 1188 | + # prevent http header injection |
| 1189 | + match = _contains_disallowed_method_pchar_re.search(method) |
| 1190 | + if match: |
| 1191 | + raise ValueError( |
| 1192 | + f"method can't contain control characters. {method!r} " |
| 1193 | + f"(found at least {match.group()!r})") |
| 1194 | + |
1180 | 1195 | def _validate_path(self, url): |
1181 | 1196 | """Validate a url for putrequest.""" |
1182 | 1197 | # Prevent CVE-2019-9740. |
|
0 commit comments