I wanted to write a brief post about the security implications of disabling bytecode verification. As the risks are already covered in the CERT secure coding guidelines
and many other excellent sources
, I have no intention of reproducing those efforts. I just want to highlight one unfortunately common myth that we sometimes still hear regarding verification: That bytecode verification is unnecessary if you only run "trusted" code.
For those of you unfamiliar with bytecode verification
, it is simply part of the JVM's classloading process that checks the code for certain dangerous and disallowed behavior. You can (but shouldn't) disable this protection on many JVMs by adding -Xverify:none or -noverify to the Java command line.
Many people still incorrectly believe that the only point of bytecode verification is to protect us from malicious code. If you believe none of the code you are running could possibly be malicious, then bytecode verification is just needless overhead, or so the thinking goes. This is absolutely incorrect. Bytecode verification is indispensable for running a secure application, regardless of the level of trust you have in the sources of each and every class you load and run.
Bytecode verification lies at the foundation of the Java security model. One of the fundamental strengths of Java security is not only its ability to safely sandbox and run untrusted code (i.e. an arbitrary applet from the Internet), but to also make guarantees about the security of trusted code. While programmers in any language must have a solid understanding of security principles and constantly think about the security implications of the code they write, there are many security mistakes that you simply can't make on the Java platform; the bytecode verifier will not let you.
If you disable bytecode verification, you are saying that not only do you trust all of the code you are running to not be malicious, you are also saying you trust every single class you load to be bug-free (at the bytecode level). This is a much higher standard than simply trusting code to not be overtly malicious.
I suspect that one of the reasons for this misconception is that people underestimate just how many different tools and components out there generate and/or modify bytecode. Do you know how your Java EE application server compiles JSP files? Do any of the frameworks in your application dynamically generate new classes during runtime (answer: most likely yes)? How about profiling / instrumentation tools like Introscope or even the method profiling built into JRockit Mission Control?
The reality is, in any sufficiently complex system, Java bytecode is being generated and modified all of the time by a large number of different tools, products, and frameworks. By disabling bytecode verification, you are trusting that all of those components in your entire stack are completely bug-free. I have seen (and sometimes fixed) many bugs in all of these types of software; they are just as likely to contain bugs as any other software.
Does this mean that there is never a reasonable time or place to disable bytecode verification? Not necessarily. One could argue that it may be appropriate in a development environment where restart time is critical and security concerns are low or even non-existent. However, even in most development environments, bytecode verification may help you discover important issues before you move to testing or production. As a general rule I always recommend leaving it enabled.
In conclusion, you should never disable bytecode verification for any system where security is a concern. These options, -Xverify:none and -noverify, were never intended to be used in production environments under any circumstances. If you are disabling bytecode verification (or any products you use have disabled verification), please consider removing these options to eliminate this security risk immediately.