High severityNVD Advisory· Published Apr 23, 2021· Updated Sep 16, 2024
Regular expression Denial of Service (ReDoS) in EmailValidator class in Vaadin 7
CVE-2020-36320
Description
Unsafe validation RegEx in EmailValidator class in com.vaadin:vaadin-server versions 7.0.0 through 7.7.21 (Vaadin 7.0.0 through 7.7.21) allows attackers to cause uncontrolled resource consumption by submitting malicious email addresses.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.vaadin:vaadin-bomMaven | >= 7.0.0.beta1, < 7.7.22 | 7.7.22 |
com.vaadin:vaadin-serverMaven | >= 7.0.0.beta1, < 7.7.22 | 7.7.22 |
Affected products
2- Vaadin/vaadin-serverv5Range: 7.0.0
Patches
22e8b9d2b5b40Open details rows shouldn't get removed when a new row is added to Grid (#12109)
3 files changed · +93 −6
client/src/main/java/com/vaadin/client/widgets/Grid.java+0 −6 modified@@ -7311,12 +7311,6 @@ public void resetDataAndSize(int newSize) { RowContainer body = escalator.getBody(); int oldSize = body.getRowCount(); - // Hide all details. - Set<Integer> oldDetails = new HashSet<>(visibleDetails); - for (int i : oldDetails) { - setDetailsVisible(i, false); - } - if (newSize > oldSize) { if (oldSize == 0 && !isHeaderVisible()) { // Fixes framework/issues/11607
uitest/src/main/java/com/vaadin/tests/components/grid/GridOpenDetailsAddRow.java+53 −0 added@@ -0,0 +1,53 @@ +package com.vaadin.tests.components.grid; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.data.provider.ListDataProvider; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +public class GridOpenDetailsAddRow extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Grid<String> testGrid = new Grid<>(); + + testGrid.addColumn(item -> item).setCaption("column").setId("column"); + + List<String> list = new ArrayList<>(); + list.add("row1"); + list.add("row2"); + list.add("row3"); + ListDataProvider<String> dataProvider = new ListDataProvider<>(list); + + testGrid.setDataProvider(dataProvider); + testGrid.setDetailsGenerator(item -> new Label("details - " + item)); + list.forEach(item -> testGrid.setDetailsVisible(item, true)); + + Button addButton = new Button("add"); + addButton.addClickListener(event -> { + String newItem = "row" + (list.size() + 1); + list.add(newItem); + testGrid.setDetailsVisible(newItem, true); + dataProvider.refreshAll(); + }); + + VerticalLayout testLayout = new VerticalLayout(addButton, testGrid); + addComponent(testLayout); + } + + @Override + protected Integer getTicketNumber() { + return 12106; + } + + @Override + protected String getTestDescription() { + return "Already open details rows shouldn't disappear when a new row is added"; + } +}
uitest/src/test/java/com/vaadin/tests/components/grid/GridOpenDetailsAddRowTest.java+40 −0 added@@ -0,0 +1,40 @@ +package com.vaadin.tests.components.grid; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridOpenDetailsAddRowTest extends MultiBrowserTest { + + @Test + public void addRow() { + openTestURL(); + waitUntilLoadingIndicatorNotVisible(); + + // confirm initial state + List<WebElement> spacers = findElements(By.className("v-grid-spacer")); + assertEquals("Unexpected initial amount of spacers", 3, spacers.size()); + + // add a row + $(ButtonElement.class).first().click(); + waitUntilLoadingIndicatorNotVisible(); + + // ensure all existing spacers are still visible, as well as the new one + spacers = findElements(By.className("v-grid-spacer")); + assertEquals("Unexpected amount of spacers after adding a row", 4, + spacers.size()); + + assertEquals("Unexpected spacer contents for new row", "details - row4", + spacers.get(3).getText()); + + assertEquals("Unexpected spacer contents for first row", + "details - row1", spacers.get(0).getText()); + } +}
17f5c1b66938Update regexp pattern to safer one (#12104)
2 files changed · +13 −2
server/src/main/java/com/vaadin/data/validator/EmailValidator.java+7 −2 modified@@ -34,6 +34,12 @@ @SuppressWarnings("serial") public class EmailValidator extends RegexpValidator { + private static final String PATTERN = "^" + "([a-zA-Z0-9_\\.\\-+])+" // local + + "@" + "[a-zA-Z0-9-.]+" // domain + + "\\." + "[a-zA-Z0-9-]{2,}" // tld + + "$"; + + /** * Creates a validator for checking that a string is a syntactically valid * e-mail address. @@ -42,7 +48,6 @@ public class EmailValidator extends RegexpValidator { * the message to display in case the value does not validate. */ public EmailValidator(String errorMessage) { - super("^([a-zA-Z0-9_\\.\\-+])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9]{2,4})+$", - true, errorMessage); + super(PATTERN, true, errorMessage); } }
server/src/test/java/com/vaadin/tests/data/validator/EmailValidatorTest.java+6 −0 modified@@ -28,4 +28,10 @@ public void testEmailValidatorWithFaultyString() { public void testEmailValidatorWithOkEmail() { Assert.assertTrue(validator.isValid("my.name@email.com")); } + + @Test + public void testEmailValidatorWithBadInput() { + Assert.assertFalse(validator.isValid("a@a.m5qRt8zLxQG4mMeu9yKZm5qRt8zLxQG4mMeu9yKZm5qRt8zLxQG4mMeu9yKZ&")); + } + }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-42j4-733x-5vcfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-36320ghsaADVISORY
- github.com/vaadin/framework/issues/7757ghsax_refsource_MISCWEB
- github.com/vaadin/framework/pull/12104ghsax_refsource_MISCWEB
- github.com/vaadin/framework/security/advisories/GHSA-42j4-733x-5vcfghsaWEB
- vaadin.com/security/cve-2020-36320ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.