JDK-8255433 : Clarify missing access check for protected or public nested type in non-public enclosing class
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2020-10-25
  • Updated: 2024-06-13
Related Reports
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
It appears that using reflection it is possible to access the members of a protected or public type which is inside a non-public enclosing class.
JLS 15 §15.12.4.3 hints that a little bit, but it is neither written in the JLS section §6.6 nor in the `java.lang.reflect.AccessibleObject` documentation explicitly.

Especially for classes which is exposed to untrusted code this detail is important because otherwise malicious code could mess with implementation details.
(Might also be worth verifying that the JDK classes are not affected)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Save the code for `TopLevel1` provided below as `test1/TopLevel1.java`
2. Save the code for `TopLevel2` provided below as `test2/TopLevel2.java`
3. Compile both files
4. Run `TopLevel2`'s main method

ACTUAL -
`TopLevel2` can modify a field of a nested class within a non-public enclosing class, even with a SecurityManager in place.

---------- BEGIN SOURCE ----------
package test1;

// package-private
class TopLevel1 {
  private static class Nested1_1 {
    protected static class Nested1_2 {
      public static int i;
    }
  }
}

---------------------------------------------

package test2;

import java.lang.reflect.Field;

public class TopLevel2 {
  public static void main(String... args) throws Exception {
    System.setSecurityManager(new SecurityManager());
    Class<?> nested1_2 = Class.forName("test1.TopLevel1$Nested1_1$Nested1_2");
    Field f = nested1_2.getDeclaredField("i");
    f.set(null, 1);
  }
}
---------- END SOURCE ----------


Comments
A known behavior, see JDK-8308040 and related bugs.
27-06-2023

It is possible to access the members of a protected or public type which is inside a non-public enclosing class. However there is no explicit explanation of accessing public or protected nested fields in non-public classes anywhere in JLS or reflection javadocs. The behavior can be seen in the test code. Classes which are exposed to untrusted code this detail is important as any malicious code could mess with the implementation details.
27-10-2020