I'm an university lecturer and I'm revising my lecture on Java reflection. Other years when teaching about the horrors of suppressAccessChecks I was showing that you could set up a SecurityManager and do something like
if ("suppressAccessChecks".equals(p.getName())){
StackTraceElement[] st = Thread.currentThread().getStackTrace();
if(.. st ..) { throw new SecurityException(); }
}
In this way you can allow for whitelisted deserializers only to call suppressAccessChecks. However, now they are deprecating the SecurityManager. I think the new module system is supposed to help here, but I'm failing to find resources explaining how to support the idea of the whitelisted deserializers above.
Any hint?
With Java modules,
setAccessible
is already restricted, even without a security manager:If we assume a typical scenario of a module M using a persistence service in module P and the members are not accessible anyway, only the last bullet applies;
M
must open the package(s) toP
to enable the access override.This can be done via a qualified
opens
directiveThis way, only the explicitly specified module(s), i.e.
P
, can usesetAccessible
for members of types inaPackage.needing.persistence
.In case of the HotSpot JVM, there’s the option
--add-opens
allowing to add qualifiedopens
relationships at startup, in addition to declared ones, but there is no option for a module of an already running application to create such a relationship at runtime to gain additional access rights itself (unless the security is already subverted). It’s imaginable that other environments do not even support such a startup option.It’s worth mentioning that there are still some new restrictions which can’t be circumvented this way. As also mentioned in
setAccessible
’s documentation:See also this answer
In other words, in case of a
record
type, the persistence service still must use the constructor to deserialize an instance, even when suppressing access checks.