Alert: Java’s Forward-Compatibility Promise Has Been Revised

Java’s Forward-Compatibility Promise

Writing forward-compatible software is really hard. You carefully write your programs strictly according to the current specifications for your target platform, and it works perfectly well on that platform.  But eventually that platform and its specifications will be updated.  It will effectively become a different platform, and you really have no way to know whether the implicit assumptions you had made will still hold.  Some internal implementation detail may have changed that breaks your program, or the rules for the new platform disallow behaviors you had depended upon, such as storing data in a particular location, or expecting that since “foo” was not a language keyword it wouldn’t become one in the next version.

The makers of the Java programming language and Java Runtime Environment (JRE) thought they had it figured out.  Their answer was that different versions of Java could be installed and run side by side, and if your app was known to work with a specific JRE (say, version 1.2.2 Update 14), you could always just specify that version and use it.  If a newer version of the JRE were installed, everything would be fine as long as the version you needed were also still installed.  Your app would simply continue to use the older version.  Write once, test once, run forever.  Forward compatibility guaranteed!  Brilliant!

Naturally, many responsible and conscientious developers continue to leverage this feature to ensure that their code continues to perform as originally tested.  “It was developed, tested and known to work on 1.2.2_14 and so we require that version.”  In particular, I see many custom, internal line of business (LOB) apps at my customers that require a specific, old JRE version.

The Promise Revised

Well, it seemed like a good idea at the time.

Back then, “older version” was not automatically considered to be synonymous with “riddled with easily exploitable security bugs.”  However, many JRE updates are Critical Patch Updates (CPUs) that fix such bugs.  You cannot keep the older version and be protected against exploits.  Why?  Because any web app can specify any vulnerable JRE you happen to have installed and run attack code on your computer. Further, the older JRE families (JRE 1.5/5.0 family and earlier, as well as JInitiator) are no longer supported and so while malware authors can continue to develop attacks for those older versions, the vulnerabilities are not being fixed and just remain exploitable.  Further, Oracle points out that older, unsupported versions may also be vulnerable to newly-discovered flaws found in newer, supported versions:

“Unsupported products, releases and versions are not tested for the presence of vulnerabilities addressed by this Critical Patch Update. However, it is likely that earlier versions of affected releases are also affected by these vulnerabilities. Hence Oracle recommends that customers upgrade their Oracle products to a supported version.”

“Critical Patch Update patches are not provided for product versions that are no longer supported. We recommend that customers upgrade to the latest supported version of Oracle products in order to obtain patches.”

Meanwhile, vulnerable versions of Java have become the most widely attacked software component on Windows computers.  It was about a year ago that the Microsoft Malware Protection Center first reported observing a sudden, large spike in attacks on Java, following a more modest but significant rise reported earlier by Symantec.  The latest Microsoft Security Intelligence Report (v11) confirms that Java remains the top target of malware, with Java exploits “responsible for between one-third and one-half of all exploits observed in each of the four most recent quarters.”

Should you continue to use older versions of Java, or even have them installed on your systems?  Probably not – the risk is obviously high.  Oracle (which acquired Sun Microsystems and Java) specifically recommends that you do not.  Says Oracle:

We highly recommend users remove all older versions of Java from your system.

Keeping old and unsupported versions of Java on your system presents a serious security risk.

A customer recently asked me what the risks would be to standardize on 1.6 Update 17.  (As of this writing, the current public JRE is 1.6 Update 27.)  Here are the JRE updates that have shipped since Update 17, going back to March 2010.  They fix a total of 94 separate vulnerabilities, which are listed on the bottom of each of these pages:

In addition, only the latest versions of Java work on Windows 7, and versions of JRE 1.6 before Update 24 won’t work with IE9.

So What Do You Do Now?

So what can you do if you are using Java?  First, you should follow Oracle’s recommendation and uninstall all but the latest supported version.  Next, you should remove the requirement from your Java apps tying them to a specific version.  Won’t all those apps break?  That can be determined only through testing, but Oracle says that “the latest available version is always compatible with the older versions,” and goes on to say:

However, some Java applications (or applets) can indicate that they are dependent on a particular version, and may not run if you do not have that version installed. If an application or web page you access requires an older version of Java, you should report this to the provider/developer and request that they update the application to be compatible with all Java versions.

If that compatibility expectation is as reliable as Oracle says, then keeping your JRE patched should be as regular and uneventful as deploying Windows “Patch Tuesday” updates.  Nobody performs comprehensive regression tests of all their applications before deploying Windows patches, because those patches almost never cause an app not to work.

Quite honestly, the alternative is too risky.  Your Java developers should no longer insist that your house be protected with broken locks.