CVE-2025-43746
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.0 through 2024.Q3.13, 2024.Q2.0 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_portletNamespace and _com_liferay_dynamic_data_mapping_web_portlet_DDMPortlet_namespace 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 | — |
ccom.liferay:com.liferay.dynamic.data.mapping.webMaven | < 5.0.122 | 5.0.122 |
Affected products
2- Liferay/DXPv5Range: 7.4.13
Patches
31 file changed · +14 −13
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+14 −13 modified@@ -34,34 +34,35 @@ public class RenderStructureFieldMVCResourceCommandTest { @Test public void testCreateDDMFormFieldRenderingContext() { - String maliciousScript = "'\"></option><img onerror=alert(123) src=x>"; - HttpServletRequest mockHttpServletRequest = Mockito.mock( + HttpServletRequest httpServletRequest = Mockito.mock( HttpServletRequest.class); ThemeDisplay themeDisplay = Mockito.mock(ThemeDisplay.class); Mockito.when( - mockHttpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) + themeDisplay.getLocale() ).thenReturn( - themeDisplay + LocaleUtil.US ); Mockito.when( - mockHttpServletRequest.getParameter("namespace") + httpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) ).thenReturn( - maliciousScript + themeDisplay ); + String script = "'\"></option><img onerror=alert(123) src=x>"; + Mockito.when( - mockHttpServletRequest.getParameter("portletNamespace") + httpServletRequest.getParameter("namespace") ).thenReturn( - maliciousScript + script ); Mockito.when( - themeDisplay.getLocale() + httpServletRequest.getParameter("portletNamespace") ).thenReturn( - LocaleUtil.US + script ); RenderStructureFieldMVCResourceCommand @@ -74,14 +75,14 @@ public void testCreateDDMFormFieldRenderingContext() { DDMFormFieldRenderingContext ddmFormFieldRenderingContext = renderStructureFieldMVCResourceCommand. createDDMFormFieldRenderingContext( - mockHttpServletRequest, + httpServletRequest, Mockito.mock(HttpServletResponse.class)); Assert.assertEquals( - HtmlUtil.escapeAttribute(maliciousScript), + HtmlUtil.escapeAttribute(script), ddmFormFieldRenderingContext.getNamespace()); Assert.assertEquals( - HtmlUtil.escapeAttribute(maliciousScript), + HtmlUtil.escapeAttribute(script), ddmFormFieldRenderingContext.getPortletNamespace()); }
7ac0f245435aLPD-55453 Add unit test
3 files changed · +128 −31
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web/src/main/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommand.java+30 −30 modified@@ -50,36 +50,7 @@ public class RenderStructureFieldMVCResourceCommand extends BaseMVCResourceCommand { - @Override - protected void doServeResource( - ResourceRequest resourceRequest, ResourceResponse resourceResponse) - throws Exception { - - HttpServletResponse httpServletResponse = - _portal.getHttpServletResponse(resourceResponse); - - HttpServletRequest httpServletRequest = _portal.getHttpServletRequest( - resourceRequest); - - DDMFormField ddmFormField = _getDDMFormField(httpServletRequest); - - DDMFormFieldRenderer ddmFormFieldRenderer = - _ddmFormFieldRendererRegistry.getDDMFormFieldRenderer( - ddmFormField.getType()); - - DDMFormFieldRenderingContext ddmFormFieldRenderingContext = - _createDDMFormFieldRenderingContext( - httpServletRequest, httpServletResponse); - - String ddmFormFieldHTML = ddmFormFieldRenderer.render( - ddmFormField, ddmFormFieldRenderingContext); - - httpServletResponse.setContentType(ContentTypes.TEXT_HTML); - - ServletResponseUtil.write(httpServletResponse, ddmFormFieldHTML); - } - - private DDMFormFieldRenderingContext _createDDMFormFieldRenderingContext( + protected DDMFormFieldRenderingContext createDDMFormFieldRenderingContext( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { @@ -121,6 +92,35 @@ private DDMFormFieldRenderingContext _createDDMFormFieldRenderingContext( return ddmFormFieldRenderingContext; } + @Override + protected void doServeResource( + ResourceRequest resourceRequest, ResourceResponse resourceResponse) + throws Exception { + + HttpServletResponse httpServletResponse = + _portal.getHttpServletResponse(resourceResponse); + + HttpServletRequest httpServletRequest = _portal.getHttpServletRequest( + resourceRequest); + + DDMFormField ddmFormField = _getDDMFormField(httpServletRequest); + + DDMFormFieldRenderer ddmFormFieldRenderer = + _ddmFormFieldRendererRegistry.getDDMFormFieldRenderer( + ddmFormField.getType()); + + DDMFormFieldRenderingContext ddmFormFieldRenderingContext = + createDDMFormFieldRenderingContext( + httpServletRequest, httpServletResponse); + + String ddmFormFieldHTML = ddmFormFieldRenderer.render( + ddmFormField, ddmFormFieldRenderingContext); + + httpServletResponse.setContentType(ContentTypes.TEXT_HTML); + + ServletResponseUtil.write(httpServletResponse, ddmFormFieldHTML); + } + private DDMFormField _getDDMFormField( HttpServletRequest httpServletRequest) {
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/build.gradle+8 −1 modified@@ -1,6 +1,13 @@ dependencies { + testImplementation group: "com.liferay", name: "jakarta.ws.rs", version: "3.1.0.LIFERAY-PATCHED-1" + testImplementation group: "com.liferay", name: "org.osgi.service.jaxrs", version: "1.0.0.JAKARTA-LIFERAY-PATCHED-1" + testImplementation group: "com.liferay.jakarta.portlet", name: "com.liferay.jakarta.portlet-api", version: "4.0.0" + testImplementation group: "com.liferay.portal", name: "com.liferay.portal.impl", version: "default" + testImplementation group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "default" + testImplementation group: "jakarta.servlet", name: "jakarta.servlet-api", version: "6.0.0" + testImplementation project(":apps:dynamic-data-mapping:dynamic-data-mapping-api") + testImplementation project(":apps:dynamic-data-mapping:dynamic-data-mapping-web") testIntegrationImplementation group: "org.osgi", name: "org.osgi.service.cm", version: "1.6.0" - testIntegrationImplementation project(":apps:dynamic-data-mapping:dynamic-data-mapping-api") testIntegrationImplementation project(":apps:dynamic-data-mapping:dynamic-data-mapping-test-util") testIntegrationImplementation project(":apps:export-import:export-import-api") testIntegrationImplementation project(":apps:export-import:export-import-test-util")
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web-test/src/test/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommandTest.java+90 −0 added@@ -0,0 +1,90 @@ +/** + * SPDX-FileCopyrightText: (c) 2025 Liferay, Inc. https://liferay.com + * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 + */ + +package com.liferay.dynamic.data.mapping.web.internal.portlet.action; + +import com.liferay.dynamic.data.mapping.render.DDMFormFieldRenderingContext; +import com.liferay.portal.kernel.test.ReflectionTestUtil; +import com.liferay.portal.kernel.theme.ThemeDisplay; +import com.liferay.portal.kernel.util.HtmlUtil; +import com.liferay.portal.kernel.util.LocaleUtil; +import com.liferay.portal.kernel.util.Portal; +import com.liferay.portal.kernel.util.WebKeys; +import com.liferay.portal.test.rule.LiferayUnitTestRule; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Test; + +import org.mockito.Mockito; + +/** + * @author Mateus Xavier + */ +public class RenderStructureFieldMVCResourceCommandTest { + + @ClassRule + public static final LiferayUnitTestRule liferayUnitTestRule = + LiferayUnitTestRule.INSTANCE; + + @Test + public void testCreateDDMFormFieldRenderingContext() { + String maliciousScript = "'\"></option><img onerror=alert(123) src=x>"; + HttpServletRequest mockHttpServletRequest = Mockito.mock( + HttpServletRequest.class); + + ThemeDisplay themeDisplay = Mockito.mock(ThemeDisplay.class); + + Mockito.when( + mockHttpServletRequest.getAttribute(WebKeys.THEME_DISPLAY) + ).thenReturn( + themeDisplay + ); + + Mockito.when( + mockHttpServletRequest.getParameter("namespace") + ).thenReturn( + maliciousScript + ); + + Mockito.when( + mockHttpServletRequest.getParameter("portletNamespace") + ).thenReturn( + maliciousScript + ); + + Mockito.when( + themeDisplay.getLocale() + ).thenReturn( + LocaleUtil.US + ); + + RenderStructureFieldMVCResourceCommand + renderStructureFieldMVCResourceCommand = + new RenderStructureFieldMVCResourceCommand(); + + ReflectionTestUtil.setFieldValue( + renderStructureFieldMVCResourceCommand, "_portal", _portal); + + DDMFormFieldRenderingContext ddmFormFieldRenderingContext = + renderStructureFieldMVCResourceCommand. + createDDMFormFieldRenderingContext( + mockHttpServletRequest, + Mockito.mock(HttpServletResponse.class)); + + Assert.assertEquals( + HtmlUtil.escapeAttribute(maliciousScript), + ddmFormFieldRenderingContext.getNamespace()); + Assert.assertEquals( + HtmlUtil.escapeAttribute(maliciousScript), + ddmFormFieldRenderingContext.getPortletNamespace()); + } + + private final Portal _portal = Mockito.mock(Portal.class); + +} \ No newline at end of file
5ca8331da450LPD-55453 Escape Parameter URL in RenderStructureFieldMVCResourceCommand
1 file changed · +5 −3
modules/apps/dynamic-data-mapping/dynamic-data-mapping-web/src/main/java/com/liferay/dynamic/data/mapping/web/internal/portlet/action/RenderStructureFieldMVCResourceCommand.java+5 −3 modified@@ -19,6 +19,7 @@ import com.liferay.portal.kernel.servlet.ServletResponseUtil; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ContentTypes; +import com.liferay.portal.kernel.util.HtmlUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.Portal; import com.liferay.portal.kernel.util.Validator; @@ -91,8 +92,8 @@ private DDMFormFieldRenderingContext _createDDMFormFieldRenderingContext( httpServletRequest.setAttribute(WebKeys.PORTLET_ID, portletId); } - String portletNamespace = ParamUtil.getString( - httpServletRequest, "portletNamespace"); + String portletNamespace = HtmlUtil.escapeAttribute( + ParamUtil.getString(httpServletRequest, "portletNamespace")); httpServletRequest.setAttribute( "aui:form:portletNamespace", portletNamespace); @@ -111,7 +112,8 @@ private DDMFormFieldRenderingContext _createDDMFormFieldRenderingContext( ddmFormFieldRenderingContext.setMode( ParamUtil.getString(httpServletRequest, "mode")); ddmFormFieldRenderingContext.setNamespace( - ParamUtil.getString(httpServletRequest, "namespace")); + HtmlUtil.escapeAttribute( + ParamUtil.getString(httpServletRequest, "namespace"))); ddmFormFieldRenderingContext.setPortletNamespace(portletNamespace); ddmFormFieldRenderingContext.setReadOnly( ParamUtil.getBoolean(httpServletRequest, "readOnly"));
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
7- github.com/advisories/GHSA-mpww-r37c-vxjwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-43746ghsaADVISORY
- github.com/liferay/liferay-portal/commit/5ca8331da4503ae336818a747e43817066f27b73ghsaWEB
- github.com/liferay/liferay-portal/commit/7ac0f245435a18e42291186907ad6dbf0e4e8a43ghsaWEB
- github.com/liferay/liferay-portal/commit/c4c34a13094356160474c06c3a115723d97f75abghsaWEB
- liferay.atlassian.net/browse/LPE-18244ghsaWEB
- liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/CVE-2025-43746ghsaWEB
News mentions
0No linked articles in our index yet.