From 2d01a1ba8984e0483ce6619b972832377f208a0d Mon Sep 17 00:00:00 2001
From: Kevin Chung <kchung@nyu.edu>
Date: Sun, 21 Mar 2021 10:03:09 -0400
Subject: [PATCH] Add HTML-5 "formaction" attribute to "defs.link_attrs"
 (GH-316)

https://github.com/lxml/lxml/commit/2d01a1ba8984e0483ce6619b972832377f208a0d

Resolves https://bugs.launchpad.net/lxml/+bug/1888153
See https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-28957
---
 src/lxml/html/defs.py             |  2 ++
 src/lxml/html/tests/test_clean.py | 15 +++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/src/lxml/html/defs.py b/src/lxml/html/defs.py
index b21a113..e40c808 100644
--- a/src/lxml/html/defs.py
+++ b/src/lxml/html/defs.py
@@ -21,6 +21,8 @@ link_attrs = frozenset([
     'usemap',
     # Not standard:
     'dynsrc', 'lowsrc',
+    # HTML5 formaction
+    'formaction'
     ])
 
 # Not in the HTML 4 spec:
diff --git a/src/lxml/html/tests/test_clean.py b/src/lxml/html/tests/test_clean.py
index 0e669f9..45c2e83 100644
--- a/src/lxml/html/tests/test_clean.py
+++ b/src/lxml/html/tests/test_clean.py
@@ -123,6 +123,21 @@ class CleanerTest(unittest.TestCase):
             b'<math><style>/* deleted */</style></math>',
             lxml.html.tostring(clean_html(s)))
 
+    def test_formaction_attribute_in_button_input(self):
+        # The formaction attribute overrides the form's action and should be
+        # treated as a malicious link attribute
+        html = ('<form id="test"><input type="submit" formaction="javascript:alert(1)"></form>'
+        '<button form="test" formaction="javascript:alert(1)">X</button>')
+        expected = ('<div><form id="test"><input type="submit" formaction=""></form>'
+        '<button form="test" formaction="">X</button></div>')
+        cleaner = Cleaner(
+            forms=False,
+            safe_attrs_only=False,
+        )
+        self.assertEqual(
+            expected,
+            cleaner.clean_html(html))
+
 
 def test_suite():
     suite = unittest.TestSuite()
-- 
1.8.3.1

