CVE-2019-10174
Description
In Infinispan, the public invokeAccessibly method in ReflectionUtil allowed any application class to invoke private methods, enabling privilege escalation.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In Infinispan, the public `invokeAccessibly` method in `ReflectionUtil` allowed any application class to invoke private methods, enabling privilege escalation.
Vulnerability
Overview
CVE-2019-10174 is a security flaw in Infinispan, a distributed in-memory data store. The vulnerability resides in the ReflectionUtil class, where the invokeAccessibly method was declared public, allowing any application class to invoke private methods in any class with Infinispan's privileges [1]. This breaks the intended access control boundaries, as the method was designed to be used internally but was exposed to all application code.
Exploitation
Prerequisites
An attacker can exploit this vulnerability by writing malicious code that calls ReflectionUtil.invokeAccessibly to reflectively access and invoke private methods within the Infinispan runtime. The attack does not require special authentication beyond being able to run code within the application's classpath [1]. The method's public visibility effectively grants any arbitrary class the same reflective capabilities as Infinispan internal code.
Impact
Successful exploitation allows an attacker to leverage reflection to introduce new, malicious behavior into the application [1]. Since private methods can be invoked, the attacker can manipulate internal state, bypass security checks, and potentially achieve privilege escalation or other unauthorized actions within the Infinispan process.
Mitigation
The vulnerability was fixed by changing the method visibility: in commit 5dbb05c, invokeAccessibly was removed and replaced with a non-public invokeMethod that uses standard Java reflection with proper exception handling [2]. Red Hat also released a security update (RHSA-2020:0727) for Red Hat Data Grid 7.3.3, which includes this fix [4]. Users should update to the patched version immediately.
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.infinispan:infinispan-coreMaven | < 8.2.12.Final | 8.2.12.Final |
org.infinispan:infinispan-coreMaven | >= 9.0.0.Final, < 9.4.17.Final | 9.4.17.Final |
Affected products
2- Infinispan/Infinispandescription
Patches
27bdc2822ccf7ISPN-9600 ReflectionUtil.invokeAccessibly should not be public
6 files changed · +86 −52
commons/src/main/java/org/infinispan/commons/util/ReflectionUtil.java+24 −4 modified@@ -2,6 +2,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -178,16 +179,36 @@ private static Field findFieldRecursively(Class<?> c, String fieldName) { * @param parameters parameters */ public static Object invokeAccessibly(Object instance, Method method, Object[] parameters) { - return SecurityActions.invokeAccessibly(instance, method, parameters); + method.setAccessible(true); + return invokeMethod(instance, method, parameters); + } + + public static Object invokeMethod(Object instance, Method method, Object[] parameters) { + try { + return method.invoke(instance, parameters); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause() != null ? e.getCause() : e; + throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance + .getClass().getSimpleName()) + + (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), cause); + } catch (Exception e) { + throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance + .getClass().getSimpleName()) + + (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), e); + } } public static void setAccessibly(Object instance, Field field, Object value) { + field.setAccessible(true); + setField(instance, field, value); + } + + public static void setField(Object instance, Field field, Object value) { try { - field.setAccessible(true); field.set(instance, value); } catch (Exception e) { throw new CacheException("Unable to set field " + field.getName() + " on object of type " + - (instance == null ? "null" : instance.getClass().getName()) + " to " + value, e); + (instance == null ? "null" : instance.getClass().getName()) + " to " + value, e); } } @@ -290,7 +311,6 @@ public static Object getValue(Object instance, String fieldName) { * @param ann annotation to search for. Must be a class-level annotation. * @return the annotation instance, or null */ - @SuppressWarnings("unchecked") public static <T extends Annotation> T getAnnotation(Class<?> clazz, Class<T> ann) { while (true) { // first check class
commons/src/main/java/org/infinispan/commons/util/SecurityActions.java+0 −21 modified@@ -1,12 +1,7 @@ package org.infinispan.commons.util; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Arrays; - -import org.infinispan.commons.CacheException; /** * Privileged actions for the package @@ -72,22 +67,6 @@ private static <T> T doPrivileged(PrivilegedAction<T> action) { } } - static Object invokeAccessibly(Object instance, Method method, Object[] parameters) { - return doPrivileged(() -> { - try { - method.setAccessible(true); - return method.invoke(instance, parameters); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause() != null ? e.getCause() : e; - throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance.getClass().getSimpleName()) + - (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), cause); - } catch (Exception e) { - throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance.getClass().getSimpleName()) + - (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), e); - } - }); - } - static ClassLoader[] getClassLoaders(ClassLoader appClassLoader) { return doPrivileged(() -> new ClassLoader[]{ appClassLoader, // User defined classes
core/src/main/java/org/infinispan/distribution/group/impl/GroupManagerImpl.java+7 −4 modified@@ -1,6 +1,6 @@ package org.infinispan.distribution.group.impl; -import static org.infinispan.commons.util.ReflectionUtil.invokeAccessibly; +import static org.infinispan.commons.util.ReflectionUtil.invokeMethod; import java.lang.reflect.Method; import java.security.AccessController; @@ -84,12 +84,15 @@ private static class GroupMetadataImpl implements GroupMetadata { @Override public Object getGroup(Object instance) { - Object object; if (System.getSecurityManager() == null) { - return invokeAccessibly(instance, method, Util.EMPTY_OBJECT_ARRAY); + method.setAccessible(true); } else { - return AccessController.doPrivileged((PrivilegedAction<Object>) () -> invokeAccessibly(instance, method, Util.EMPTY_OBJECT_ARRAY)); + AccessController.doPrivileged((PrivilegedAction<List<Method>>) () -> { + method.setAccessible(true); + return null; + }); } + return invokeMethod(instance, method, Util.EMPTY_OBJECT_ARRAY); } }
core/src/main/java/org/infinispan/factories/impl/BasicComponentRegistryImpl.java+10 −22 modified@@ -1,10 +1,5 @@ package org.infinispan.factories.impl; -import static org.infinispan.commons.util.ReflectionUtil.invokeAccessibly; -import static org.infinispan.commons.util.ReflectionUtil.setAccessibly; - -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -306,12 +301,8 @@ private void invokeInjectionMethod(Object target, ComponentMetadata.InjectMethod Object value = getDependency(name, parameterComponentTypes[i], parameterLazy, startDependencies); params[i] = value; } - if (System.getSecurityManager() == null) { - invokeAccessibly(target, injectMethodMetadata.getMethod(), params); - } else { - AccessController.doPrivileged( - (PrivilegedAction<Object>) () -> invokeAccessibly(target, injectMethodMetadata.getMethod(), params)); - } + SecurityActions.setAccessible(injectMethodMetadata.getMethod()); + ReflectionUtil.invokeMethod(target, injectMethodMetadata.getMethod(), params); } private void setInjectionField(Object target, ComponentMetadata.InjectFieldMetadata injectFieldMetadata, @@ -320,14 +311,8 @@ private void setInjectionField(Object target, ComponentMetadata.InjectFieldMetad boolean lazy = injectFieldMetadata.isLazy(); Class<?> componentType = injectFieldMetadata.getComponentClass(); Object value = getDependency(name, componentType, lazy, startDependencies); - if (System.getSecurityManager() == null) { - setAccessibly(target, injectFieldMetadata.getField(), value); - } else { - AccessController.doPrivileged((PrivilegedAction<Void>) () -> { - setAccessibly(target, injectFieldMetadata.getField(), value); - return null; - }); - } + SecurityActions.setAccessible(injectFieldMetadata.getField()); + ReflectionUtil.setField(target, injectFieldMetadata.getField(), value); } private Object getDependency(String name, Class<?> componentType, boolean lazy, boolean startDependencies) { @@ -531,10 +516,12 @@ void startWrapper(ComponentWrapper wrapper) { try { for (ComponentMetadata.PrioritizedMethodMetadata method : wrapper.metadata.getStartMethods()) { - ReflectionUtil.invokeAccessibly(wrapper.instance, method.getMethod(), null); + SecurityActions.setAccessible(method.getMethod()); + ReflectionUtil.invokeMethod(wrapper.instance, method.getMethod(), null); } for (ComponentMetadata.PrioritizedMethodMetadata method : wrapper.metadata.getPostStartMethods()) { - ReflectionUtil.invokeAccessibly(wrapper.instance, method.getMethod(), null); + SecurityActions.setAccessible(method.getMethod()); + ReflectionUtil.invokeMethod(wrapper.instance, method.getMethod(), null); } commitWrapperStateChange(wrapper, WrapperState.STARTING, WrapperState.STARTED); @@ -605,7 +592,8 @@ private void performStop(ComponentWrapper wrapper) { try { for (ComponentMetadata.PrioritizedMethodMetadata method : wrapper.metadata.getStopMethods()) { - ReflectionUtil.invokeAccessibly(wrapper.instance, method.getMethod(), null); + SecurityActions.setAccessible(method.getMethod()); + ReflectionUtil.invokeMethod(wrapper.instance, method.getMethod(), null); } } catch (Exception e) { log.error("Error stopping component " + wrapper.name, e);
core/src/main/java/org/infinispan/factories/impl/SecurityActions.java+43 −0 added@@ -0,0 +1,43 @@ +package org.infinispan.factories.impl; + +import java.lang.reflect.AccessibleObject; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.infinispan.security.Security; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; + +/** + * SecurityActions for the org.infinispan.factories package. + * <p> + * Do not move. Do not change class and method visibility to avoid being called from other + * {@link java.security.CodeSource}s, thus granting privilege escalation to external code. + * + * @author Dan Berindei + * @since 9.4 + */ +final class SecurityActions { + private static final Log log = LogFactory.getLog(SecurityActions.class); + + static <T> void doPrivileged(PrivilegedAction<T> runnable) { + if (System.getSecurityManager() != null) { + AccessController.doPrivileged((PrivilegedAction<Void>) () -> { + runnable.run(); + return null; + }); + } else { + Security.doPrivileged((PrivilegedAction<Void>) () -> { + runnable.run(); + return null; + }); + } + } + + static void setAccessible(AccessibleObject member) { + doPrivileged(() -> { + member.setAccessible(true); + return null; + }); + } +}
core/src/test/java/org/infinispan/test/TestingUtil.java+2 −1 modified@@ -1948,7 +1948,8 @@ public static void stopComponent(Object component) { public static void invokeLifecycle(Object component, Class<? extends Annotation> lifecycle) { List<Method> methods = ReflectionUtil.getAllMethods(component.getClass(), lifecycle); for (Method m : methods) { - ReflectionUtil.invokeAccessibly(component, m, EMPTY_OBJECT_ARRAY); + m.setAccessible(true); + ReflectionUtil.invokeMethod(component, m, EMPTY_OBJECT_ARRAY); } }
5dbb05cfaca0ISPN-9600 ReflectionUtil.invokeAccessibly should not be public
5 files changed · +37 −37
commons/src/main/java/org/infinispan/commons/util/ReflectionUtil.java+14 −3 modified@@ -6,6 +6,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -161,8 +162,19 @@ private static Field findFieldRecursively(Class<?> c, String fieldName) { * @param method method to execute * @param parameters parameters */ - public static Object invokeAccessibly(Object instance, Method method, Object[] parameters) { - return SecurityActions.invokeAccessibly(instance, method, parameters); + public static Object invokeMethod(Object instance, Method method, Object[] parameters) { + try { + return method.invoke(instance, parameters); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause() != null ? e.getCause() : e; + throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance + .getClass().getSimpleName()) + + (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), cause); + } catch (Exception e) { + throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance + .getClass().getSimpleName()) + + (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), e); + } } public static Method findGetterForField(Class<?> c, String fieldName) { @@ -260,7 +272,6 @@ public static Object getValue(Object instance, String fieldName) { * @param ann annotation to search for. Must be a class-level annotation. * @return the annotation instance, or null */ - @SuppressWarnings("unchecked") public static <T extends Annotation> T getAnnotation(Class<?> clazz, Class<T> ann) { while (true) { // first check class
commons/src/main/java/org/infinispan/commons/util/SecurityActions.java+0 −21 modified@@ -1,12 +1,7 @@ package org.infinispan.commons.util; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Arrays; - -import org.infinispan.commons.CacheException; /** * Privileged actions for the package @@ -84,22 +79,6 @@ private static <T> T doPrivileged(PrivilegedAction<T> action) { } } - static Object invokeAccessibly(Object instance, Method method, Object[] parameters) { - return doPrivileged((PrivilegedAction<Object>) () -> { - try { - method.setAccessible(true); - return method.invoke(instance, parameters); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause() != null ? e.getCause() : e; - throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance.getClass().getSimpleName()) + - (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), cause); - } catch (Exception e) { - throw new CacheException("Unable to invoke method " + method + " on object of type " + (instance == null ? "null" : instance.getClass().getSimpleName()) + - (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), e); - } - }); - } - static ClassLoader[] getClassLoaders(ClassLoader appClassLoader) { return doPrivileged((PrivilegedAction<ClassLoader[]>) () -> { return new ClassLoader[] { appClassLoader, // User defined classes
core/src/main/java/org/infinispan/distribution/group/GroupManagerImpl.java+7 −5 modified@@ -1,6 +1,6 @@ package org.infinispan.distribution.group; -import static org.infinispan.commons.util.ReflectionUtil.invokeAccessibly; +import static org.infinispan.commons.util.ReflectionUtil.invokeMethod; import org.infinispan.commons.util.CollectionFactory; import org.infinispan.commons.util.ReflectionUtil; @@ -50,13 +50,15 @@ public GroupMetadataImpl(Method method) { @Override public String getGroup(Object instance) { - Object object; if (System.getSecurityManager() == null) { - object = invokeAccessibly(instance, method, Util.EMPTY_OBJECT_ARRAY); + method.setAccessible(true); } else { - object = AccessController.doPrivileged((PrivilegedAction<Object>) () -> invokeAccessibly(instance, method, Util.EMPTY_OBJECT_ARRAY)); + AccessController.doPrivileged((PrivilegedAction<List<Method>>) () -> { + method.setAccessible(true); + return null; + }); } - return String.class.cast(object); + return String.class.cast(invokeMethod(instance, method, Util.EMPTY_OBJECT_ARRAY)); } }
core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java+8 −8 modified@@ -21,7 +21,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; @@ -35,8 +34,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; -import static org.infinispan.commons.util.ReflectionUtil.invokeAccessibly; - /** * A registry where components which have been created are stored. Components are stored as singletons, registered * under a specific name. @@ -245,11 +242,7 @@ private void invokeInjectionMethod(Object o, ComponentMetadata.InjectMetadata in boolean nameIsFQCN = !injectMetadata.isParameterNameSet(i); params[i] = getOrCreateComponent(dependencies[i], name, nameIsFQCN); } - if (System.getSecurityManager() == null) { - invokeAccessibly(o, injectMetadata.getMethod(), params); - } else { - AccessController.doPrivileged((PrivilegedAction<Object>) () -> invokeAccessibly(o, injectMetadata.getMethod(), params)); - } + invokeAccessibly(o, injectMetadata.getMethod(), params); } } @@ -465,6 +458,13 @@ public void rewire() { } } + private static Object invokeAccessibly(Object instance, Method method, Object[] parameters) { + return SecurityActions.doPrivileged(() -> { + method.setAccessible(true); + return ReflectionUtil.invokeMethod(instance, method, parameters); + }); + } + /** * Scans each registered component for lifecycle methods, and adds them to the appropriate lists, and then sorts them * by priority.
core/src/main/java/org/infinispan/factories/SecurityActions.java+8 −0 modified@@ -21,6 +21,14 @@ final class SecurityActions { private static final Log log = LogFactory.getLog(SecurityActions.class); + static <T> T doPrivileged(PrivilegedAction<T> action) { + if (System.getSecurityManager() != null) { + return AccessController.doPrivileged(action); + } else { + return action.run(); + } + } + private static Field findFieldRecursively(Class<?> c, String fieldName) { Field f = null; try {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- access.redhat.com/errata/RHSA-2020:0481ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2020:0727ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-h47x-2j37-fw5mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-10174ghsaADVISORY
- bugzilla.redhat.com/show_bug.cgighsax_refsource_CONFIRMWEB
- github.com/infinispan/infinispan/commit/5dbb05cfaca01a1a66732b82a0f5ba615ccbd214ghsaWEB
- github.com/infinispan/infinispan/commit/7bdc2822ccf79127a488130239c49a5e944e3ca2ghsaWEB
- security.netapp.com/advisory/ntap-20220210-0018ghsaWEB
- security.netapp.com/advisory/ntap-20220210-0018/mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.