Moderate severityNVD Advisory· Published Aug 22, 2025· Updated Aug 22, 2025
CVE-2025-43762
CVE-2025-43762
Description
Liferay Portal 7.4.0 through 7.4.3.132, and Liferay DXP 2025.Q1.0 through 2025.Q1.1, 2024.Q4.0 through 2024.Q4.7, 2024.Q3.1 through 2024.Q3.13, 2024.Q2.0 through 2024.Q2.13, 2024.Q1.1 through 2024.Q1.14 and 7.4 GA through update 92 allow users to upload an unlimited amount of files through the forms, the files are stored in the document_library allowing an attacker to cause a potential DDoS.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.liferay:com.liferay.dynamic.data.mapping.form.webMaven | < 4.0.180 | 4.0.180 |
com.liferay:com.liferay.dynamic.data.mapping.form.field.typeMaven | < 6.0.187 | 6.0.187 |
Affected products
2- Liferay/DXPv5Range: 7.4.13
Patches
19d32b089f30aLPD-48341 Create temporary file deletion logic for forms upload field
6 files changed · +227 −21
modules/apps/data-engine/data-engine-js-components-web/src/main/resources/META-INF/resources/js/custom/form/components/PaginationControls.es.js+3 −0 modified@@ -88,6 +88,9 @@ export function PaginationControls({ <ClayButton className="float-left" id="ddm-form-submit" + onClick={() => { + Liferay.fire('paginationControlsSubmitButtonClicked'); + }} type="submit" > {submitLabel}
modules/apps/dynamic-data-mapping/dynamic-data-mapping-form-field-type/src/main/java/com/liferay/dynamic/data/mapping/form/field/type/internal/document/library/DocumentLibraryDDMFormFieldTemplateContextContributor.java+19 −0 modified@@ -106,6 +106,25 @@ public Map<String, Object> getParameters( return ddmFormInstanceRecordId; } + ).put( + "fileEntryDeleteURL", + () -> { + HttpServletRequest httpServletRequest = + ddmFormFieldRenderingContext.getHttpServletRequest(); + + RequestBackedPortletURLFactory requestBackedPortletURLFactory = + RequestBackedPortletURLFactoryUtil.create( + httpServletRequest); + + return PortletURLBuilder.create( + requestBackedPortletURLFactory.createActionURL( + GetterUtil.getString( + _portal.getPortletId(httpServletRequest), + DDMPortletKeys.DYNAMIC_DATA_MAPPING_FORM)) + ).setActionName( + "/dynamic_data_mapping_form/delete_file_entry" + ).buildString(); + } ).put( "groupId", ddmFormFieldRenderingContext.getProperty("groupId") ).put(
modules/apps/dynamic-data-mapping/dynamic-data-mapping-form-field-type/src/main/resources/META-INF/resources/DocumentLibrary/DocumentLibrary.es.js+98 −21 modified@@ -15,7 +15,7 @@ import { useFormState, } from 'data-engine-js-components-web'; import {formatStorage, openSelectionModal, sub} from 'frontend-js-web'; -import React, {useEffect, useMemo, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import FieldBase from '../FieldBase/ReactFieldBase.es'; @@ -257,6 +257,7 @@ const Main = ({ editingLanguageId, errorMessage: initialErrorMessage, fieldName, + fileEntryDeleteURL, fileEntryTitle, fileEntryURL, guestUploadURL, @@ -285,6 +286,7 @@ const Main = ({ const [displayErrors, setDisplayErrors] = useState(initialDisplayErrors); const [valid, setValid] = useState(initialValid); const [progress, setProgress] = useState(0); + const [submitButtonClicked, setSubmitButtonClicked] = useState(false); const isSignedIn = Liferay.ThemeDisplay.isSignedIn(); @@ -473,9 +475,73 @@ const Main = ({ return true; }; - const handleUploadSelectButtonClicked = (event) => { + const deleteFileEntry = useCallback(() => { + const request = new XMLHttpRequest(); + + let oldFileEntryId = 0; + + try { + const fileEntry = JSON.parse(value); + + oldFileEntryId = fileEntry.fileEntryId; + } + catch (error) { + console.error('Unable to parse JSON', value); + } + + request.open('POST', fileEntryDeleteURL); + request.send( + convertToFormData({ + [`${portletNamespace}oldFileEntryId`]: oldFileEntryId, + }) + ); + }, [fileEntryDeleteURL, portletNamespace, value]); + + const handleOnClearButtonClicked = (event, isSignedIn) => { + onFocus(event); + + deleteFileEntry(); + + setCurrentValue(null); + + onChange(event, '{}'); + + if (!isSignedIn) { + const guestUploadInput = document.getElementById( + `${name}inputFileGuestUpload` + ); + + if (guestUploadInput) { + guestUploadInput.value = ''; + } + + onBlur(event); + } + }; + + const handleUploadSelectButtonClicked = (event, currentValue) => { onFocus(event); + let oldFileEntryId = 0; + + if (currentValue) { + try { + const fileEntry = JSON.parse(currentValue); + + oldFileEntryId = fileEntry.fileEntryId; + + uploadFileEntry(event, oldFileEntryId); + } + catch (error) { + console.error('Unable to parse JSON', currentValue); + } + } + else { + uploadFileEntry(event, oldFileEntryId); + } + }; + + const uploadFileEntry = (event, oldFileEntryId) => { const file = event.target.files[0]; if (isExceededUploadRequestSizeLimit(file.size)) { @@ -529,6 +595,7 @@ const Main = ({ request.send( convertToFormData({ [`${portletNamespace}file`]: file, + [`${portletNamespace}oldFileEntryId`]: oldFileEntryId, }) ); }; @@ -538,6 +605,32 @@ const Main = ({ maximumSubmissionLimitReached || showUploadPermissionMessage; + useEffect(() => { + window.onbeforeunload = function () { + if (!submitButtonClicked) { + deleteFileEntry(); + } + }; + + return () => { + window.onbeforeunload = null; + }; + }, [deleteFileEntry, submitButtonClicked]); + + useEffect(() => { + Liferay.on( + 'paginationControlsSubmitButtonClicked', + + () => { + setSubmitButtonClicked(true); + } + ); + + return () => { + Liferay.detach('paginationControlsSubmitButtonClicked'); + }; + }, []); + return ( <FieldBase {...otherProps} @@ -559,25 +652,11 @@ const Main = ({ name={name} onBlur={onBlur} onClearButtonClicked={(event) => { - onFocus(event); - - setCurrentValue(null); - - onChange(event, '{}'); - - const guestUploadInput = document.getElementById( - `${name}inputFileGuestUpload` - ); - - if (guestUploadInput) { - guestUploadInput.value = ''; - } - - onBlur(event); + handleOnClearButtonClicked(event, value, isSignedIn); }} onFocus={onFocus} onUploadSelectButtonClicked={(event) => - handleUploadSelectButtonClicked(event) + handleUploadSelectButtonClicked(event, currentValue) } placeholder={placeholder} progress={progress} @@ -596,9 +675,7 @@ const Main = ({ message={message} name={name} onClearButtonClicked={(event) => { - setCurrentValue(null); - - onChange(event, '{}'); + handleOnClearButtonClicked(event, value, isSignedIn); }} onSelectButtonClicked={(event) => handleSelectButtonClicked(
modules/apps/dynamic-data-mapping/dynamic-data-mapping-form-web/src/main/java/com/liferay/dynamic/data/mapping/form/web/internal/portlet/action/DeleteFileEntryMVCActionCommand.java+45 −0 added@@ -0,0 +1,45 @@ +/** + * 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.form.web.internal.portlet.action; + +import com.liferay.document.library.kernel.service.DLFileEntryLocalService; +import com.liferay.dynamic.data.mapping.constants.DDMPortletKeys; +import com.liferay.dynamic.data.mapping.form.web.internal.portlet.action.util.DLFileEntryUtil; +import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand; +import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand; + +import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; + +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * @author Igor Costa + */ +@Component( + property = { + "javax.portlet.name=" + DDMPortletKeys.DYNAMIC_DATA_MAPPING_FORM, + "javax.portlet.name=" + DDMPortletKeys.DYNAMIC_DATA_MAPPING_FORM_ADMIN, + "mvc.command.name=/dynamic_data_mapping_form/delete_file_entry" + }, + service = MVCActionCommand.class +) +public class DeleteFileEntryMVCActionCommand extends BaseMVCActionCommand { + + @Override + protected void doProcessAction( + ActionRequest actionRequest, ActionResponse actionResponse) + throws Exception { + + DLFileEntryUtil.deleteDLFileEntry( + actionRequest, _dlFileEntryLocalService); + } + + @Reference + private DLFileEntryLocalService _dlFileEntryLocalService; + +} \ No newline at end of file
modules/apps/dynamic-data-mapping/dynamic-data-mapping-form-web/src/main/java/com/liferay/dynamic/data/mapping/form/web/internal/portlet/action/UploadFileEntryMVCActionCommand.java+9 −0 modified@@ -10,9 +10,11 @@ import com.liferay.document.library.kernel.exception.FileSizeException; import com.liferay.document.library.kernel.exception.InvalidFileException; import com.liferay.document.library.kernel.model.DLFileEntry; +import com.liferay.document.library.kernel.service.DLFileEntryLocalService; import com.liferay.dynamic.data.mapping.constants.DDMActionKeys; import com.liferay.dynamic.data.mapping.constants.DDMFormConstants; import com.liferay.dynamic.data.mapping.constants.DDMPortletKeys; +import com.liferay.dynamic.data.mapping.form.web.internal.portlet.action.util.DLFileEntryUtil; import com.liferay.dynamic.data.mapping.form.web.internal.security.permission.resource.DDMFormInstancePermission; import com.liferay.dynamic.data.mapping.form.web.internal.upload.DDMFormUploadValidator; import com.liferay.dynamic.data.mapping.model.DDMFormInstance; @@ -99,6 +101,9 @@ protected void doProcessAction( @Reference(target = "(upload.response.handler.system.default=true)") private UploadResponseHandler _defaultUploadResponseHandler; + @Reference + private DLFileEntryLocalService _dlFileEntryLocalService; + @Reference private Language _language; @@ -121,6 +126,10 @@ private class DDMFormUploadFileEntryHandler public FileEntry upload(UploadPortletRequest uploadPortletRequest) throws IOException, PortalException { + DLFileEntryUtil.deleteDLFileEntry( + uploadPortletRequest.getPortletRequest(), + _dlFileEntryLocalService); + File file = null; try {
modules/apps/dynamic-data-mapping/dynamic-data-mapping-form-web/src/main/java/com/liferay/dynamic/data/mapping/form/web/internal/portlet/action/util/DLFileEntryUtil.java+53 −0 added@@ -0,0 +1,53 @@ +/** + * 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.form.web.internal.portlet.action.util; + +import com.liferay.document.library.kernel.model.DLFileEntry; +import com.liferay.document.library.kernel.service.DLFileEntryLocalService; +import com.liferay.dynamic.data.mapping.util.DDMFormUtil; +import com.liferay.portal.kernel.exception.PortalException; +import com.liferay.portal.kernel.model.User; +import com.liferay.portal.kernel.theme.ThemeDisplay; +import com.liferay.portal.kernel.util.ParamUtil; +import com.liferay.portal.kernel.util.WebKeys; + +import javax.portlet.PortletRequest; + +/** + * @author Igor Costa + */ +public class DLFileEntryUtil { + + public static void deleteDLFileEntry( + PortletRequest portletRequest, + DLFileEntryLocalService dlFileEntryLocalService) + throws PortalException { + + long fileEntryId = ParamUtil.getLong(portletRequest, "oldFileEntryId"); + + if (fileEntryId == 0) { + return; + } + + DLFileEntry dlFileEntry = dlFileEntryLocalService.fetchDLFileEntry( + fileEntryId); + + if (dlFileEntry == null) { + return; + } + + ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute( + WebKeys.THEME_DISPLAY); + + User user = DDMFormUtil.getDDMFormDefaultUser( + themeDisplay.getCompanyId()); + + if (dlFileEntry.getUserId() == user.getUserId()) { + dlFileEntryLocalService.deleteFileEntry(fileEntryId); + } + } + +} \ No newline at end of file
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
5- github.com/advisories/GHSA-84pp-qr92-95c9ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-43762ghsaADVISORY
- github.com/liferay/liferay-portal/commit/9d32b089f30a42c8fd2d30832b3c90eefb5afe84ghsaWEB
- liferay.atlassian.net/browse/LPE-18177ghsaWEB
- liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/CVE-2025-43762ghsaWEB
News mentions
0No linked articles in our index yet.