Repository: scrapy/scrapy

Issue:
Whitelist form methods in FormRequest.from_response
Hi team, according to this [article](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method), there are 3 methods that are accepted in form's `method` attribute. I can't remember about other methods, but I'd agree to consider the rest of [REST verbs](https://restfulapi.net/http-methods/) if that's common. Anyway, I think it should be a good idea to whitelist the accepted methods to avoid scenarios like this [vulnerability exploitation](https://medium.com/alertot/web-scraping-considered-dangerous-exploiting-the-telnet-service-in-scrapy-1-5-2-ad5260fea0db) that took advantage of form's method.

This issue affects `FormRequest.from_response` and the affected line is: https://github.com/scrapy/scrapy/blob/a3d38041e230f886d55569f861a11a96ab8a1913/scrapy/http/request/form.py#L51

I want to know if there some reason behind this behavior, otherwise I could send a pull request.

Discussion:

Patch:
diff --git a/scrapy/http/request/form.py b/scrapy/http/request/form.py
index c2413b431..3ce8fc48e 100644
--- a/scrapy/http/request/form.py
+++ b/scrapy/http/request/form.py
@@ -18,6 +18,7 @@ from scrapy.utils.response import get_base_url
 
 
 class FormRequest(Request):
+    valid_form_methods = ['GET', 'POST']
 
     def __init__(self, *args, **kwargs):
         formdata = kwargs.pop('formdata', None)
@@ -48,7 +49,13 @@ class FormRequest(Request):
         form = _get_form(response, formname, formid, formnumber, formxpath)
         formdata = _get_inputs(form, formdata, dont_click, clickdata, response)
         url = _get_form_url(form, kwargs.pop('url', None))
+
         method = kwargs.pop('method', form.method)
+        if method is not None:
+            method = method.upper()
+            if method not in cls.valid_form_methods:
+                method = 'GET'
+
         return cls(url=url, method=method, formdata=formdata, **kwargs)
 
 


Test patch:
diff --git a/tests/test_http_request.py b/tests/test_http_request.py
index 49f148016..258b48dce 100644
--- a/tests/test_http_request.py
+++ b/tests/test_http_request.py
@@ -1100,6 +1100,20 @@ class FormRequestTest(RequestTest):
         self.assertRaises(ValueError, self.request_class.from_response,
                           response, formcss="input[name='abc']")
 
+    def test_from_response_valid_form_methods(self):
+        body = """<form action="post.php" method="%s">
+            <input type="hidden" name="one" value="1">
+            </form>"""
+
+        for method in self.request_class.valid_form_methods:
+            response = _buildresponse(body % method)
+            r = self.request_class.from_response(response)
+            self.assertEqual(r.method, method)
+
+        response = _buildresponse(body % 'UNKNOWN')
+        r = self.request_class.from_response(response)
+        self.assertEqual(r.method, 'GET')
+
 
 def _buildresponse(body, **kwargs):
     kwargs.setdefault('body', body)