CodeQL 文档

getResource 的不安全使用

ID: java/unsafe-get-resource
Kind: problem
Security severity: 
Severity: warning
Precision: medium
Tags:
   - reliability
   - maintainability
Query suites:
   - java-security-and-quality.qls

单击以在 CodeQL 代码库中查看查询

使用 Class.getResource 方法是将一些非代码资源包含在应用程序中的常见方法。

当使用 x.getClass().getResource()(对于某些变量 x)调用此方法时存在问题。这并不是检索资源的安全方法。方法 getClass 返回 x运行时类(即,它的实际,“最派生”类,而不是其声明类型),这会导致两个潜在问题。

  • 如果接收对象的运行时类型是声明类型的子类,并且位于不同的包中,则资源路径的解释可能会有所不同。根据其约定,Class.getResource 使用当前包名限定非绝对路径,从而可能返回不同的资源或无法找到请求的资源。

  • Class.getResource 将查找资源的任务委托给加载该类的类加载器。在运行时,不能保证某个类型的子类都由同一个类加载器加载,这会导致难以诊断的资源查找失败。

建议

与其使用依赖于动态分派和运行时类型的getClass 方法,不如使用class 字面量。例如,不要在类型为Foo 的对象上调用getClass().getResource(),而是调用Foo.class.getResource()。类字面量始终引用它们所使用的声明类型,从而消除了对运行时类型的依赖。

示例

在以下示例中,对getPostalCodes 的调用返回不同的结果,具体取决于调用所针对的类:类Address 在包framework 中,而类UKAddress 在包client 中。

package framework;
class Address {
    public URL getPostalCodes() {
        // AVOID: The call is made on the run-time type of 'this'.
        return this.getClass().getResource("postal-codes.csv");
    }
}

package client;
class UKAddress extends Address {
    public void convert() {
        // Looks up "framework/postal-codes.csv"
        new Address().getPostalCodes();
        // Looks up "client/postal-codes.csv"
        new UKAddress().getPostalCodes();
    }
}

在以下更正后的示例中,getPostalCodes 的实现进行了更改,以便它始终对同一个类调用getResource

package framework;
class Address {
    public URL getPostalCodes() {
        // GOOD: The call is always made on an object of the same type.
        return Address.class.getResource("postal-codes.csv");
    }
}

package client;
class UKAddress extends Address {
    public void convert() {
        // Looks up "framework/postal-codes.csv"
        new Address().getPostalCodes();
        // Looks up "framework/postal-codes.csv"
        new UKAddress().getPostalCodes();
    }
}

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私