Lightning Web セキュリティのしくみ

Lightning Web セキュリティの目的は、Lightning Locker と同様に、Lightning コンポーネントが他の名前空間のプラットフォームコードやコンポーネントに属するデータに干渉したり、アクセスしたりするのを防ぐことです。Lightning Web セキュリティのアーキテクチャは、異なる手法で Lightning Web コンポーネントを保護します。

Salesforce ページには、複数の企業が作成したコンポーネントを含めることができます。組織の開発者チームが作成したコンポーネントと、Salesforce が作成したコンポーネントは共存できます。自分でアプリケーションを作成して AppExchange にリリースした場合、自分のコンポーネントは、Salesforce が作成したコンポーネント、および自分のアプリケーションをインストールした顧客のコンポーネントと共存します。

予防策を講じなければ、コンポーネントが window グローバルオブジェクトにアクセスし、ページ上の他のコンポーネントから非公開リソースやデータを取得できてしまいます。予防策の 1 つとして、コンポーネントを名前空間で分離する方法があります。このようにすれば、悪意のあるコンポーネントがその名前空間の外部にあるコンポーネントのリソースにアクセスできなくなります。

業界では一般的に、分離を実現するために仮想化が用いられます。コードは仮想環境、つまりホストの環境のレプリカ内で実行されます。仮想環境では、ホストのリソースの一部が、仮想環境で実行中のコードに公開されます。ホスト環境で、複数の仮想環境が同時に実行されますが、ある仮想環境で動作するコードは、他の仮想環境のリソースにアクセスできません。悪意のあるコードは、実行先の仮想環境にしか影響を与えることができません。

仮想環境は、ホスト環境で動作する仮想化エンジンによって作成および管理されます。仮想化エンジンは、ホスト環境のリソースにフルにアクセスできますが、個々の仮想環境で使用可能なリソースを厳格に管理します。ハードウェアプラットフォームやオペレーティングシステムレベルの仮想化エンジンには、VMWare や Docker などがあります。

仮想化の概念を Web アプリケーションのレベルにまで落とし込むことで、ホスト環境がブラウザの範疇に収まります。Lightning Web セキュリティは、ホスト環境で動作する仮想化エンジンで、仮想環境の構築と管理を行うものです。名前空間の JavaScript Sandbox は仮想環境です。Lightning Web セキュリティは、各仮想環境で、ホスト環境からの特定のリソースへのアクセスを制限付きで許可します。このリソースには、グローバルオブジェクト、ネットワークアクセス、Cookie アクセス、ローカルストレージなどがあります。

ブラウザ仮想化の比較図

Lightning Web セキュリティは、コンポーネントをその名前空間独自の仮想環境で実行し、JavaScript API レベルでコードを変更することにより、安全ではない動作を防止できます。修正 (ディストーション) は Sandbox で適用されます。

Sandbox による仮想化の効果を示すために、いくつかの Cookie を参照してみましょう。コンポーネントは、Cookie を保存できます。LWS などのプラットフォームコードも、Cookie を保存できます。ブラウザのホスト環境では、コードは無制限に実行されます。LWS を有効にしない場合、コンポーネントコードがその領域で実行され、制限なしにすべての Cookie にアクセス可能になり、その中のすべての情報が参照可能になり、さらに Cookie へのあらゆる操作が可能になります。コンポーネントの Cookie を、他のコードがアクセスできる場所に保存しないでください。LWS を有効にした場合、コンポーネントコードを名前空間の Sandbox で実行することで保護できます。コンポーネントが Cookie にアクセスする場合、コンポーネントが設定した Cookie か、コンポーネントからアクセス可能な Cookie しか参照できません。これは、Cookie を Sandbox に入れることで LWS がアクセス可能な Cookie を制御するためです。

たとえば、c 名前空間の Sandbox では、コンポーネントは設定した foo=1 Cookie にしかアクセスできません。LWS は、ブラウザのホスト環境では、キーにプレフィックスを付加して、コンポーネントの Sandbox と関連付けるため、その Cookie が異なる形式で表示されます。この Cookie を参照する必要があるコードは、Sandbox 環境で実行され、foo=1 を想定している場合に、Cookie を参照できます。コンポーネントは、ブラウザのホスト環境では Cookie にアクセスできないため、Cookie のキーが変更されたことを認識する必要はありません。Sandbox で Cookie の値が変更された場合、LWS がホスト環境での Cookie の値の更新を実行します。LWS は Cookie のキープレフィックスを管理し、名前空間の Sandbox に関連付けるため、別の名前空間のコンポーネントからホスト環境の Cookie にはアクセスできません。

Cookie のプレフィックスは LSKey-{namespace}$ なので、この例では Cookie のキーが LSKey-c$foo に変更されます。プレフィックスは、内部実装の詳細と見なされるため、予告なく変更されることがあります。作成するコードでは、プレフィックスが固定であると想定しないでください。サーバから受け取った Cookie には、ブラウザの開発者向けツールで確認できるプレフィックスが付けられています。たとえば、Chrome DevTools の Application タブには、Cookie の詳細が表示されます。

Lightning Locker で使用されているセキュアなラッパーの代わりに、Lightning Web セキュリティでは、ディストーションと呼ばれる手法が使用されます。これは、JavaScript Sandbox 内で実行されるコードを変更して、安全ではない動作を防ぐ手法です。

ディストーションは、ネイティブ JavaScript API を次の目的で動的に変更します。

  • JavaScript Sandbox の外部のコンテンツやデータを変更しようとする API の試行の防止
  • 実行中のコードを Sandbox の境界内に封じ込める
  • JavaScript Sandbox 内で、DOM、window.location などの共有グローバルオブジェクト、および Cookie などのデータへのアクセスを制限または削減する

Lightning Web セキュリティの API のディストーションは、ほとんどが次の 3 つに分類されます。

  • コンテンツフィルタリング — 他の Sandbox のプロパティ (document.cookielocalStoragesessionStorage など) にアクセスする試みを排除し、一方で現在のサンドボックス内でのアクセスは許可します。
  • サニタイズ — innerHTMLouterHTML 要素から悪意のあるコードを排除します
  • プロパティアクセス機構の変更 — 特定のプロパティの値を読み書きできないようにします (例: shadowRoot.mode)

ディストーションについては、「LWS Distortion Viewer」で説明されています。これは、個々のディストーションの影響を簡単に理解できるように設計されたツールのことです。