ネイティブ・イメージのセキュリティに関する考慮事項

native-imageビルダーは、起動後にアプリケーションのスナップショットを生成し、バイナリ実行可能ファイルにバンドルします。

クラスの初期化

native-imageビルダーでは、ビルド時に特定のクラスの静的イニシャライザを実行できます(詳細はクラスの初期化に関する項を参照)。ビルド時に静的イニシャライザを実行すると、初期化後の状態がイメージ・ヒープに保持されます。このことは、静的イニシャライザで取得または計算された情報が、ネイティブ・実行可能ファイルの一部になることを意味します。これにより、機密データがスナップショットに含められたり、乱数シードなど、起動時に取得されることが想定される初期化データが修正される可能性があります。

開発者は、ネイティブ実行可能ファイルのビルド時に--initialize-at-run-time CLIパラメータを指定し、その後にイメージのビルド中ではなく、実行時に初期化される必要があるパッケージとクラス(およびそのすべてのサブクラスを暗黙的に含む)のカンマ区切りリストを指定して、機密情報を処理する静的イニシャライザを実行時に実行するようリクエストできます。あるいは、開発者はRuntimeClassInitialization APIを使用することもできます。

開発者は、そもそもコンテナなどの機密情報が含まれていない専用環境でnative-imageビルダーを実行する必要があります。

ソフトウェア部品表

GraalVMネイティブ・イメージは、ビルド時にソフトウェア部品表(SBOM)を埋め込んで、既知のセキュリティの脆弱性の影響を受ける可能性のあるライブラリを検出できます。ネイティブ・イメージには、SBOMをネイティブ実行可能ファイルに埋め込むための--enable-sbomオプションが用意されています。

ノート: ソフトウェア部品表(SBOM)の埋込みは、GraalVM Community Editionでは使用できません。

CycloneDX形式がサポートされており、デフォルトです。CycloneDX SBOMをネイティブ実行可能ファイルに埋め込むには、--enable-sbomオプションをnative-imageコマンドに渡します。

この実装では、ネイティブ実行可能ファイルに含まれるクラスについて、外部ライブラリ・マニフェストで監視可能なすべてのバージョン情報をリカバリすることによってSBOMが構築されます。また、SBOMは、ネイティブ実行可能ファイル・サイズへの影響を抑えるために圧縮されます。
SBOMはgzip形式で格納され、エクスポートされたsbomシンボルはその開始アドレスを参照し、sbom_lengthシンボルはそのサイズを参照します。

圧縮されたSBOMを実行可能ファイルに埋め込んだ後、ネイティブ・イメージ検査ツールでオプションの--sbomパラメータを使用して($JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary>)、実行可能ファイルと共有ライブラリの両方から圧縮されたSBOMを抽出できます。SBOMは次の形式で出力されます:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "components": [
    {
      "type": "library",
      "group": "io.netty",
      "name": "netty-codec-http2",
      "version": "4.1.76.Final",
      "properties": [
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:codec:codec:4.1.76.Final:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:codec:netty-codec-http2:4.1.76.Final:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:codec:netty_codec_http2:4.1.76.Final:*:*:*:*:*:*:*"
        },
        ...
      ]
    },
    ...
  ],
  "serialNumber": "urn:uuid:51ec305f-616e-4139-a033-a094bb94a17c"
}

脆弱なライブラリをスキャンするには、脆弱性スキャナにSBOMを送信します。たとえば、一般的なAnchoreソフトウェア・サプライ・チェーン管理プラットフォームでは、grypeスキャナを無料で入手できます。SBOMで指定されたライブラリに、Anchoreのデータベースに記載されている既知の脆弱性があるかどうかを確認できます。この目的のために、コマンド$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary> | grypeを使用してツールの出力をgrypeスキャナに直接送り、脆弱なライブラリを確認できます。次のような出力が生成されます:

NAME                 INSTALLED      VULNERABILITY   SEVERITY
netty-codec-http2    4.1.76.Final   CVE-2022-24823  Medium

このレポートを使用して、実行可能ファイルで見つかった脆弱性依存関係を更新できます。

ネイティブ・イメージでのJavaのシリアライズ

ネイティブ・イメージではシリアライズがサポートされており、ネイティブの実行可能ファイルに含まれているクラスのコンストラクタをユーザーがデシリアライズできます。ネイティブ・イメージ分析によって自動的にピックアップされないかぎり、ネイティブ実行可能ファイルに含まれていないクラスはデシリアライズできないため、これらのクラスは事前に指定する必要があります。ネイティブ・イメージは、デシリアライズの脆弱性の悪用を単独で防ぐことはできません。Java SEのシリアライズおよびデシリアライズ・セキュア・コーディング・ガイドラインに従う必要があります。

その他

ネイティブ・イメージには、デフォルトのTrustStoreの定義に使用される証明書ファイルを指定する複数の方法が用意されています。native-imageのデフォルト動作では、ビルド時のホスト環境からデフォルトのTrustStoreを取得して使用しますが、これは実行時にjavax.net.ssl.trustStore*システム・プロパティを設定して変更できます。詳細は、ドキュメントを参照してください。

実行時にSystem.loadLibrary()を使用してネイティブ・ライブラリをロードする場合、ネイティブ実行可能ファイルを含むディレクトリは検索パスの一部です。

ネイティブ・イメージでは、Javaセキュリティ・マネージャを有効にできません。この機能がJava 17以降非推奨になったためです。セキュリティ・マネージャを設定しようとすると、ランタイム・エラーが発生します。