Unsafe use of getResource¶
ID: java/unsafe-get-resourceKind: problemSecurity severity: Severity: warningPrecision: mediumTags: - quality - reliability - correctnessQuery suites: - java-security-and-quality.qls
Click to see the query in the CodeQL repository
Using theClass.getResource method is a common way of including some non-code resources with an application.
There are problems when this is called usingx.getClass().getResource(), for some variablex. This is not a safe way to retrieve a resource. The methodgetClass returns therun-time class ofx (that is, its actual, “most derived” class, rather than its declared type), which causes two potential problems:
If the run-time type of the receiving object is a subclass of the declared type and is in a different package, the resource path may be interpreted differently. According to its contract,
Class.getResourcequalifies non-absolute paths with the current package name, thus potentially returning a different resource or failing to find the requested resource.Class.getResourcedelegates finding the resource to the class loader that loaded the class. At run time, there is no guarantee that all subclasses of a particular type are loaded by the same class loader, resulting in resource lookup failures that are difficult to diagnose.
Recommendation¶
Rather than using thegetClass method, which relies on dynamic dispatch and run-time types, useclass literals instead. For example, instead of callinggetClass().getResource() on an object of typeFoo, callFoo.class.getResource(). Class literals always refer to the declared type they are used on, removing the dependency on run-time types.
Example¶
In the following example, the calls togetPostalCodes return different results, depending on which class the call is made on: the classAddress is in the packageframework and the classUKAddress is in the packageclient.
packageframework;classAddress{publicURLgetPostalCodes(){// AVOID: The call is made on the run-time type of 'this'.returnthis.getClass().getResource("postal-codes.csv");}}packageclient;classUKAddressextendsAddress{publicvoidconvert(){// Looks up "framework/postal-codes.csv"newAddress().getPostalCodes();// Looks up "client/postal-codes.csv"newUKAddress().getPostalCodes();}}
In the following corrected example, the implementation ofgetPostalCodes is changed so that it always callsgetResource on the same class.
packageframework;classAddress{publicURLgetPostalCodes(){// GOOD: The call is always made on an object of the same type.returnAddress.class.getResource("postal-codes.csv");}}packageclient;classUKAddressextendsAddress{publicvoidconvert(){// Looks up "framework/postal-codes.csv"newAddress().getPostalCodes();// Looks up "framework/postal-codes.csv"newUKAddress().getPostalCodes();}}
References¶
Java API Specification:Class.getResource().