CWE-492, Use of Inner Class Containing Sensitive Data, covers Java inner classes that hold or touch data meant to stay private. MITRE lists Java.
How it happens
In source code, an inner class seems to be reachable only from its enclosing class. But Java bytecode has no concept of an inner class. The compiler turns each one into a peer class with package level access to the original outer class.
There is a second effect. An inner class can use private fields of its outer class. Once it becomes a peer class, the compiler converts those private fields into protected fields so the peer can reach them.
public class Vault {
private String secret = loadSecret();
private class Reader { // looks private
String read() { return secret; } // forces secret to widen in bytecode
}
}
The source shows two private members. The compiled result is less strict than that.
What an attacker gains
MITRE lists one impact: reading application data. The data confidentiality of inner classes can often be overcome. The record has no observed CVEs.
How to find it
Static analysis can find some instances. You can also review which inner classes touch private fields that hold keys, tokens or personal data.
How to fix it
MITRE gives two points.
- Use sealed classes, which protect object oriented encapsulation and stop code from being extended in unforeseen ways.
- Remember that inner classes do not provide security. Never reduce the security of an object by moving from an outer class to an inner class. If the outer class is final or private, make its inner class private as well.
In practice, keep sensitive values out of any class that shares a package with untrusted code, and pass data in as method arguments instead of exposing outer fields.
Quick check
Is a private inner class hidden from other code?
Only in the source. In bytecode it becomes a package level class, so source level privacy is not a security boundary.