VYPR
High severityNVD Advisory· Published Jun 16, 2025· Updated Jun 16, 2025

CVE-2025-3602

CVE-2025-3602

Description

Liferay Portal 7.4.0 through 7.4.3.97, and Liferay DXP 2023.Q3.1 through 2023.Q3.2, 7.4 GA through update 92, 7.3 GA through update 35, and 7.2 fix pack 8 through fix pack 20 does not limit the depth of a GraphQL queries, which allows remote attackers to perform denial-of-service (DoS) attacks on the application by executing complex queries.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.liferay:com.liferay.portal.vulcan.implMaven
< 5.0.1035.0.103

Affected products

2

Patches

1
6c6dad38c9c8

LPS-191341 Implement a MaxQueryDepthInstrumentation to limit the depth for each GraphQL request

https://github.com/liferay/liferay-portalCarlos CorreaAug 30, 2023via ghsa
3 files changed · +66 0
  • modules/apps/portal-vulcan/portal-vulcan-impl/build.gradle+1 0 modified
    @@ -64,6 +64,7 @@ dependencies {
     	compileOnly project(":apps:headless:headless-batch-engine:headless-batch-engine-api")
     	compileOnly project(":apps:oauth2-provider:oauth2-provider-scope-api")
     	compileOnly project(":apps:oauth2-provider:oauth2-provider-scope-liferay-api")
    +	compileOnly project(":apps:portal-configuration:portal-configuration-module-configuration-api")
     	compileOnly project(":apps:portal-odata:portal-odata-api")
     	compileOnly project(":apps:portal-vulcan:portal-vulcan-api")
     	compileOnly project(":apps:static:osgi:osgi-util")
    
  • modules/apps/portal-vulcan/portal-vulcan-impl/src/main/java/com/liferay/portal/vulcan/internal/graphql/servlet/GraphQLServletExtender.java+25 0 modified
    @@ -17,6 +17,7 @@
     import com.liferay.petra.function.transform.TransformUtil;
     import com.liferay.petra.string.StringPool;
     import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition;
    +import com.liferay.portal.configuration.module.configuration.ConfigurationProvider;
     import com.liferay.portal.kernel.exception.NoSuchModelException;
     import com.liferay.portal.kernel.log.Log;
     import com.liferay.portal.kernel.log.LogFactoryUtil;
    @@ -36,6 +37,7 @@
     import com.liferay.portal.vulcan.graphql.dto.v1_0.Creator;
     import com.liferay.portal.vulcan.graphql.servlet.ServletData;
     import com.liferay.portal.vulcan.graphql.validation.GraphQLRequestContextValidator;
    +import com.liferay.portal.vulcan.internal.configuration.HeadlessAPICompanyConfiguration;
     import com.liferay.portal.vulcan.internal.configuration.VulcanCompanyConfiguration;
     import com.liferay.portal.vulcan.internal.configuration.VulcanConfiguration;
     import com.liferay.portal.vulcan.internal.configuration.util.ConfigurationUtil;
    @@ -44,6 +46,7 @@
     import com.liferay.portal.vulcan.internal.graphql.data.fetcher.LiferayMethodDataFetcher;
     import com.liferay.portal.vulcan.internal.graphql.data.processor.GraphQLDTOContributorDataFetchingProcessor;
     import com.liferay.portal.vulcan.internal.graphql.data.processor.LiferayMethodDataFetchingProcessor;
    +import com.liferay.portal.vulcan.internal.graphql.servlet.instrumentation.MaxQueryDepthInstrumentation;
     import com.liferay.portal.vulcan.internal.graphql.util.GraphQLUtil;
     import com.liferay.portal.vulcan.internal.graphql.validation.GraphQLDTOContributorRequestContext;
     import com.liferay.portal.vulcan.internal.graphql.validation.ServletDataRequestContext;
    @@ -546,6 +549,7 @@ public void keyRemoved(
     				});
     		_graphQLRequestContextValidators = ServiceTrackerListFactory.open(
     			bundleContext, GraphQLRequestContextValidator.class);
    +
     		_servletContextHelperServiceRegistration =
     			bundleContext.registerService(
     				ServletContextHelper.class,
    @@ -936,6 +940,8 @@ private Servlet _createServlet(long companyId) throws Exception {
     				GraphQLQueryInvoker.newBuilder(
     				).withExecutionStrategyProvider(
     					executionStrategyProvider
    +				).withInstrumentation(
    +					() -> _getMaxQueryDepthInstrumentation(companyId)
     				).build();
     
     			graphQLConfigurationBuilder.with(graphQLQueryInvoker);
    @@ -1056,6 +1062,22 @@ private GraphQLObjectType _getGraphQLObjectType(
     		return graphQLObjectTypeBuilder.build();
     	}
     
    +	private MaxQueryDepthInstrumentation _getMaxQueryDepthInstrumentation(
    +		long companyId) {
    +
    +		try {
    +			HeadlessAPICompanyConfiguration headlessAPICompanyConfiguration =
    +				_configurationProvider.getCompanyConfiguration(
    +					HeadlessAPICompanyConfiguration.class, companyId);
    +
    +			return new MaxQueryDepthInstrumentation(
    +				headlessAPICompanyConfiguration.queryDepthLimit());
    +		}
    +		catch (Exception exception) {
    +			throw new RuntimeException(exception);
    +		}
    +	}
    +
     	private GraphQLObjectType _getPageGraphQLObjectType(
     		GraphQLType facetGraphQLType, GraphQLType objectGraphQLType,
     		String name) {
    @@ -1854,6 +1876,9 @@ public Object serialize(Object value)
     	@Reference
     	private ConfigurationAdmin _configurationAdmin;
     
    +	@Reference
    +	private ConfigurationProvider _configurationProvider;
    +
     	private DefaultTypeFunction _defaultTypeFunction;
     
     	@Reference
    
  • modules/apps/portal-vulcan/portal-vulcan-impl/src/main/java/com/liferay/portal/vulcan/internal/graphql/servlet/instrumentation/MaxQueryDepthInstrumentation.java+40 0 added
    @@ -0,0 +1,40 @@
    +/**
    + * SPDX-FileCopyrightText: (c) 2023 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.portal.vulcan.internal.graphql.servlet.instrumentation;
    +
    +import com.liferay.petra.string.StringBundler;
    +
    +import graphql.execution.AbortExecutionException;
    +
    +/**
    + * @author Carlos Correa
    + */
    +public class MaxQueryDepthInstrumentation
    +	extends graphql.analysis.MaxQueryDepthInstrumentation {
    +
    +	public MaxQueryDepthInstrumentation(int depthQueryLimit) {
    +		super(
    +			0,
    +			queryDepthInfo ->
    +				(depthQueryLimit > 0) &&
    +				(queryDepthInfo.getDepth() > depthQueryLimit));
    +
    +		_depthQueryLimit = depthQueryLimit;
    +	}
    +
    +	@Override
    +	protected AbortExecutionException mkAbortException(
    +		int depth, int maxDepth) {
    +
    +		throw new AbortExecutionException(
    +			StringBundler.concat(
    +				"Maximum query depth exceeded ", depth, " > ",
    +				_depthQueryLimit));
    +	}
    +
    +	private final int _depthQueryLimit;
    +
    +}
    \ 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

4

News mentions

0

No linked articles in our index yet.