CVE-2025-43757
Description
A reflected cross-site scripting (XSS) vulnerability in the Liferay Portal 7.4.0 through 7.4.3.132, and Liferay DXP 2025.Q2.0 through 2025.Q2.2, 2025.Q1.0 through 2025.Q1.14, 2024.Q4.0 through 2024.Q4.7, 2024.Q3.1 through 2024.Q3.13, 2024.Q2.1 through 2024.Q2.13, 2024.Q1.1 through 2024.Q1.18 and 7.4 GA through update 92 allows a remote authenticated attacker to inject JavaScript code via _com_liferay_dynamic_data_mapping_web_portlet_DDMPortlet_definition parameter.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.liferay.portal:release.portal.bomMaven | >= 7.4.0-ga1, <= 7.4.3.132-ga132 | — |
Affected products
2- Liferay/DXPv5Range: 7.4.13
Patches
8cc46176ba414Revert "LPD-56406 Escape Parameter URL in RenderStructureFieldMVCResourceCommand"
1 file changed · +2 −2
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web/src/main/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommand.java+2 −2 modified@@ -124,8 +124,8 @@ protected void doServeResource( protected DDMFormField getDDMFormField( HttpServletRequest httpServletRequest) { - String definition = HtmlUtil.escapeAttribute( - ParamUtil.getString(httpServletRequest, "definition")); + String definition = ParamUtil.getString( + httpServletRequest, "definition"); String fieldName = ParamUtil.getString(httpServletRequest, "fieldName"); DDMFormDeserializerDeserializeRequest.Builder builder =
1 file changed · +6 −6
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+6 −6 modified@@ -99,15 +99,15 @@ public void testGetDDMFormField() { HtmlUtil.escapeAttribute(_SCRIPT) ); - DDMFormDeserializer jsonDDMFormDeserializer = Mockito.mock( + DDMFormDeserializer ddmFormDeserializer = Mockito.mock( DDMFormDeserializer.class); DDMFormDeserializerDeserializeResponse ddmFormDeserializerDeserializeResponse = Mockito.mock( DDMFormDeserializerDeserializeResponse.class); Mockito.when( - jsonDDMFormDeserializer.deserialize(Mockito.any()) + ddmFormDeserializer.deserialize(Mockito.any()) ).thenReturn( ddmFormDeserializerDeserializeResponse ); @@ -120,10 +120,10 @@ public void testGetDDMFormField() { ddmForm ); - DDMFormField ddmFormFieldMock = Mockito.mock(DDMFormField.class); + DDMFormField mockDDMFormField = Mockito.mock(DDMFormField.class); Mockito.when( - ddmFormFieldMock.getName() + mockDDMFormField.getName() ).thenReturn( HtmlUtil.escapeAttribute(_SCRIPT) ); @@ -132,7 +132,7 @@ public void testGetDDMFormField() { ddmForm.getDDMFormFieldsMap(true) ).thenReturn( Collections.singletonMap( - HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldMock) + HtmlUtil.escapeAttribute(_SCRIPT), mockDDMFormField) ); RenderStructureFieldMVCResourceCommand @@ -141,7 +141,7 @@ public void testGetDDMFormField() { ReflectionTestUtil.setFieldValue( renderStructureFieldMVCResourceCommand, "_jsonDDMFormDeserializer", - jsonDDMFormDeserializer); + ddmFormDeserializer); DDMFormField ddmFormField = renderStructureFieldMVCResourceCommand.getDDMFormField(
1 file changed · +17 −17
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+17 −17 modified@@ -99,40 +99,40 @@ public void testGetDDMFormField() { HtmlUtil.escapeAttribute(_SCRIPT) ); - DDMFormField ddmFormFieldMock = Mockito.mock(DDMFormField.class); + DDMFormDeserializer jsonDDMFormDeserializer = Mockito.mock( + DDMFormDeserializer.class); + + DDMFormDeserializerDeserializeResponse + ddmFormDeserializerDeserializeResponse = Mockito.mock( + DDMFormDeserializerDeserializeResponse.class); Mockito.when( - ddmFormFieldMock.getName() + jsonDDMFormDeserializer.deserialize(Mockito.any()) ).thenReturn( - HtmlUtil.escapeAttribute(_SCRIPT) + ddmFormDeserializerDeserializeResponse ); DDMForm ddmForm = Mockito.mock(DDMForm.class); Mockito.when( - ddmForm.getDDMFormFieldsMap(true) + ddmFormDeserializerDeserializeResponse.getDDMForm() ).thenReturn( - Collections.singletonMap( - HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldMock) + ddmForm ); - DDMFormDeserializerDeserializeResponse - ddmFormDeserializerDeserializeResponseMock = Mockito.mock( - DDMFormDeserializerDeserializeResponse.class); + DDMFormField ddmFormFieldMock = Mockito.mock(DDMFormField.class); Mockito.when( - ddmFormDeserializerDeserializeResponseMock.getDDMForm() + ddmFormFieldMock.getName() ).thenReturn( - ddmForm + HtmlUtil.escapeAttribute(_SCRIPT) ); - DDMFormDeserializer jsonDDMFormDeserializerMock = Mockito.mock( - DDMFormDeserializer.class); - Mockito.when( - jsonDDMFormDeserializerMock.deserialize(Mockito.any()) + ddmForm.getDDMFormFieldsMap(true) ).thenReturn( - ddmFormDeserializerDeserializeResponseMock + Collections.singletonMap( + HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldMock) ); RenderStructureFieldMVCResourceCommand @@ -141,7 +141,7 @@ public void testGetDDMFormField() { ReflectionTestUtil.setFieldValue( renderStructureFieldMVCResourceCommand, "_jsonDDMFormDeserializer", - jsonDDMFormDeserializerMock); + jsonDDMFormDeserializer); DDMFormField ddmFormField = renderStructureFieldMVCResourceCommand.getDDMFormField(
d001c5ba8a14LPD-56406 Not necessary for this test
1 file changed · +0 −9
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+0 −9 modified@@ -93,12 +93,6 @@ public void testCreateDDMFormFieldRenderingContext() { @Test public void testGetDDMFormField() { - Mockito.when( - _httpServletRequest.getParameter("definition") - ).thenReturn( - _SCRIPT - ); - Mockito.when( _httpServletRequest.getParameter("fieldName") ).thenReturn( @@ -145,9 +139,6 @@ public void testGetDDMFormField() { renderStructureFieldMVCResourceCommand = new RenderStructureFieldMVCResourceCommand(); - ReflectionTestUtil.setFieldValue( - renderStructureFieldMVCResourceCommand, "_portal", _portal); - ReflectionTestUtil.setFieldValue( renderStructureFieldMVCResourceCommand, "_jsonDDMFormDeserializer", jsonDDMFormDeserializerMock);
e83d102bf00aLPD-56406 Make the method protected so you can test it
2 files changed · +5 −5
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web/src/main/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommand.java+2 −2 modified@@ -103,7 +103,7 @@ protected void doServeResource( HttpServletRequest httpServletRequest = _portal.getHttpServletRequest( resourceRequest); - DDMFormField ddmFormField = _getDDMFormField(httpServletRequest); + DDMFormField ddmFormField = getDDMFormField(httpServletRequest); DDMFormFieldRenderer ddmFormFieldRenderer = _ddmFormFieldRendererRegistry.getDDMFormFieldRenderer( @@ -121,7 +121,7 @@ protected void doServeResource( ServletResponseUtil.write(httpServletResponse, ddmFormFieldHTML); } - private DDMFormField _getDDMFormField( + protected DDMFormField getDDMFormField( HttpServletRequest httpServletRequest) { String definition = HtmlUtil.escapeAttribute(
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+3 −3 modified@@ -152,9 +152,9 @@ public void testGetDDMFormField() { renderStructureFieldMVCResourceCommand, "_jsonDDMFormDeserializer", jsonDDMFormDeserializerMock); - DDMFormField ddmFormField = ReflectionTestUtil.invoke( - renderStructureFieldMVCResourceCommand, "_getDDMFormField", - new Class<?>[] {HttpServletRequest.class}, _httpServletRequest); + DDMFormField ddmFormField = + renderStructureFieldMVCResourceCommand.getDDMFormField( + _httpServletRequest); Assert.assertEquals( HtmlUtil.escapeAttribute(_SCRIPT), ddmFormField.getName());
0837982b91c5LPD-56406 Setup method with common logic
1 file changed · +27 −42
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+27 −42 modified@@ -24,6 +24,7 @@ import java.util.Collections; import org.junit.Assert; +import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; @@ -38,11 +39,8 @@ public class RenderStructureFieldMVCResourceCommandTest { public static final LiferayUnitTestRule liferayUnitTestRule = LiferayUnitTestRule.INSTANCE; - @Test - public void testCreateDDMFormFieldRenderingContext() { - HttpServletRequest httpServletRequest = Mockito.mock( - HttpServletRequest.class); - + @Before + public void setUp() throws Exception { ThemeDisplay themeDisplay = Mockito.mock(ThemeDisplay.class); Mockito.when( @@ -52,23 +50,24 @@ public void testCreateDDMFormFieldRenderingContext() { ); Mockito.when( - httpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) + _httpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) ).thenReturn( themeDisplay ); + } - String script = "'\"></option><img onerror=alert(123) src=x>"; - + @Test + public void testCreateDDMFormFieldRenderingContext() { Mockito.when( - httpServletRequest.getParameter("namespace") + _httpServletRequest.getParameter("namespace") ).thenReturn( - script + _SCRIPT ); Mockito.when( - httpServletRequest.getParameter("portletNamespace") + _httpServletRequest.getParameter("portletNamespace") ).thenReturn( - script + _SCRIPT ); RenderStructureFieldMVCResourceCommand @@ -81,56 +80,37 @@ public void testCreateDDMFormFieldRenderingContext() { DDMFormFieldRenderingContext ddmFormFieldRenderingContext = renderStructureFieldMVCResourceCommand. createDDMFormFieldRenderingContext( - httpServletRequest, + _httpServletRequest, Mockito.mock(HttpServletResponse.class)); Assert.assertEquals( - HtmlUtil.escapeAttribute(script), + HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldRenderingContext.getNamespace()); Assert.assertEquals( - HtmlUtil.escapeAttribute(script), + HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldRenderingContext.getPortletNamespace()); } @Test public void testGetDDMFormField() { - HttpServletRequest httpServletRequest = Mockito.mock( - HttpServletRequest.class); - - ThemeDisplay themeDisplay = Mockito.mock(ThemeDisplay.class); - Mockito.when( - themeDisplay.getLocale() + _httpServletRequest.getParameter("definition") ).thenReturn( - LocaleUtil.US + _SCRIPT ); Mockito.when( - httpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) + _httpServletRequest.getParameter("fieldName") ).thenReturn( - themeDisplay - ); - - String script = "'\"></option><img onerror=alert(123) src=x>"; - - Mockito.when( - httpServletRequest.getParameter("definition") - ).thenReturn( - script - ); - - Mockito.when( - httpServletRequest.getParameter("fieldName") - ).thenReturn( - HtmlUtil.escapeAttribute(script) + HtmlUtil.escapeAttribute(_SCRIPT) ); DDMFormField ddmFormFieldMock = Mockito.mock(DDMFormField.class); Mockito.when( ddmFormFieldMock.getName() ).thenReturn( - HtmlUtil.escapeAttribute(script) + HtmlUtil.escapeAttribute(_SCRIPT) ); DDMForm ddmForm = Mockito.mock(DDMForm.class); @@ -139,7 +119,7 @@ public void testGetDDMFormField() { ddmForm.getDDMFormFieldsMap(true) ).thenReturn( Collections.singletonMap( - HtmlUtil.escapeAttribute(script), ddmFormFieldMock) + HtmlUtil.escapeAttribute(_SCRIPT), ddmFormFieldMock) ); DDMFormDeserializerDeserializeResponse @@ -174,12 +154,17 @@ public void testGetDDMFormField() { DDMFormField ddmFormField = ReflectionTestUtil.invoke( renderStructureFieldMVCResourceCommand, "_getDDMFormField", - new Class<?>[] {HttpServletRequest.class}, httpServletRequest); + new Class<?>[] {HttpServletRequest.class}, _httpServletRequest); Assert.assertEquals( - HtmlUtil.escapeAttribute(script), ddmFormField.getName()); + HtmlUtil.escapeAttribute(_SCRIPT), ddmFormField.getName()); } + private static final String _SCRIPT = + "'\"></option><img onerror=alert(123) src=x>"; + + private final HttpServletRequest _httpServletRequest = Mockito.mock( + HttpServletRequest.class); private final Portal _portal = Mockito.mock(Portal.class); } \ No newline at end of file
1 file changed · +94 −0
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+94 −0 modified@@ -5,6 +5,10 @@ package com.liferay.dynamic.data.mapping.web.internal.portlet.action; +import com.liferay.dynamic.data.mapping.io.DDMFormDeserializer; +import com.liferay.dynamic.data.mapping.io.DDMFormDeserializerDeserializeResponse; +import com.liferay.dynamic.data.mapping.model.DDMForm; +import com.liferay.dynamic.data.mapping.model.DDMFormField; import com.liferay.dynamic.data.mapping.render.DDMFormFieldRenderingContext; import com.liferay.portal.kernel.test.ReflectionTestUtil; import com.liferay.portal.kernel.theme.ThemeDisplay; @@ -17,6 +21,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.util.Collections; + import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -86,6 +92,94 @@ public void testCreateDDMFormFieldRenderingContext() { ddmFormFieldRenderingContext.getPortletNamespace()); } + @Test + public void testGetDDMFormField() { + HttpServletRequest httpServletRequest = Mockito.mock( + HttpServletRequest.class); + + ThemeDisplay themeDisplay = Mockito.mock(ThemeDisplay.class); + + Mockito.when( + themeDisplay.getLocale() + ).thenReturn( + LocaleUtil.US + ); + + Mockito.when( + httpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) + ).thenReturn( + themeDisplay + ); + + String script = "'\"></option><img onerror=alert(123) src=x>"; + + Mockito.when( + httpServletRequest.getParameter("definition") + ).thenReturn( + script + ); + + Mockito.when( + httpServletRequest.getParameter("fieldName") + ).thenReturn( + HtmlUtil.escapeAttribute(script) + ); + + DDMFormField ddmFormFieldMock = Mockito.mock(DDMFormField.class); + + Mockito.when( + ddmFormFieldMock.getName() + ).thenReturn( + HtmlUtil.escapeAttribute(script) + ); + + DDMForm ddmForm = Mockito.mock(DDMForm.class); + + Mockito.when( + ddmForm.getDDMFormFieldsMap(true) + ).thenReturn( + Collections.singletonMap( + HtmlUtil.escapeAttribute(script), ddmFormFieldMock) + ); + + DDMFormDeserializerDeserializeResponse + ddmFormDeserializerDeserializeResponseMock = Mockito.mock( + DDMFormDeserializerDeserializeResponse.class); + + Mockito.when( + ddmFormDeserializerDeserializeResponseMock.getDDMForm() + ).thenReturn( + ddmForm + ); + + DDMFormDeserializer jsonDDMFormDeserializerMock = Mockito.mock( + DDMFormDeserializer.class); + + Mockito.when( + jsonDDMFormDeserializerMock.deserialize(Mockito.any()) + ).thenReturn( + ddmFormDeserializerDeserializeResponseMock + ); + + RenderStructureFieldMVCResourceCommand + renderStructureFieldMVCResourceCommand = + new RenderStructureFieldMVCResourceCommand(); + + ReflectionTestUtil.setFieldValue( + renderStructureFieldMVCResourceCommand, "_portal", _portal); + + ReflectionTestUtil.setFieldValue( + renderStructureFieldMVCResourceCommand, "_jsonDDMFormDeserializer", + jsonDDMFormDeserializerMock); + + DDMFormField ddmFormField = ReflectionTestUtil.invoke( + renderStructureFieldMVCResourceCommand, "_getDDMFormField", + new Class<?>[] {HttpServletRequest.class}, httpServletRequest); + + Assert.assertEquals( + HtmlUtil.escapeAttribute(script), ddmFormField.getName()); + } + private final Portal _portal = Mockito.mock(Portal.class); } \ No newline at end of file
9e0026c8aa44LPD-56406 Escape Parameter URL in RenderStructureFieldMVCResourceCommand
1 file changed · +2 −2
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web/src/main/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommand.java+2 −2 modified@@ -124,8 +124,8 @@ protected void doServeResource( private DDMFormField _getDDMFormField( HttpServletRequest httpServletRequest) { - String definition = ParamUtil.getString( - httpServletRequest, "definition"); + String definition = HtmlUtil.escapeAttribute( + ParamUtil.getString(httpServletRequest, "definition")); String fieldName = ParamUtil.getString(httpServletRequest, "fieldName"); DDMFormDeserializerDeserializeRequest.Builder builder =
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
12- github.com/advisories/GHSA-62pf-hcwj-rcfcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-43757ghsaADVISORY
- github.com/liferay/liferay-portal/commit/0114bb60238e5ac74b90fba37fa9748c4e6c114aghsaWEB
- github.com/liferay/liferay-portal/commit/0837982b91c5f9e837ec11a93f7e0986e00738faghsaWEB
- github.com/liferay/liferay-portal/commit/45492d30bad4084f36e87ef11c29a5bf5fb4046dghsaWEB
- github.com/liferay/liferay-portal/commit/90396a201d05be5840f99f7487578aab253dfa87ghsaWEB
- github.com/liferay/liferay-portal/commit/9e0026c8aa444937a2bfd079bcca35ab3dd18f5aghsaWEB
- github.com/liferay/liferay-portal/commit/cc46176ba4142f470d540f2343b36f12a678a240ghsaWEB
- github.com/liferay/liferay-portal/commit/d001c5ba8a1477755d7d83b8a00aba23036b045bghsaWEB
- github.com/liferay/liferay-portal/commit/e83d102bf00af3aa4396c1fc5a1d6b3842ccaeb1ghsaWEB
- liferay.atlassian.net/browse/LPE-18259ghsaWEB
- liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/CVE-2025-43757ghsaWEB
News mentions
0No linked articles in our index yet.