VYPR
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.

PackageAffected versionsPatched versions
com.liferay:com.liferay.dynamic.data.mapping.form.webMaven
< 4.0.1804.0.180
com.liferay:com.liferay.dynamic.data.mapping.form.field.typeMaven
< 6.0.1876.0.187

Affected products

2

Patches

1
9d32b089f30a

LPD-48341 Create temporary file deletion logic for forms upload field

https://github.com/liferay/liferay-portalIgor CostaFeb 10, 2025via ghsa
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

News mentions

0

No linked articles in our index yet.