コンテンツセキュリティポリシー
レスポンスごとの nonce で Base UI のスタイル・スクリプト要素を許可し、必要に応じて生成スタイルを静的 CSS に置き換えます。
CSP の動作を設定する
コンテンツセキュリティポリシーを適用するアプリケーションで、Tinyrack コンポーネントの Base UI 内部実装が <style> または <script> 要素を生成する場合は、TRCSPProvider を使用してください。2 つの機能は個別に設定します。
- サーバーレスポンスごとに nonce を生成し、HTTP ヘッダー、サーバーレンダリング、クライアントのハイドレーションへ同じ値を渡します。この nonce で Base UI のスタイル要素とスクリプト要素を許可できます。
- スタイル要素を一切レンダリングできない場合は、
disableStyleElementsも設定し、同等のスクロールバー規則を静的スタイルシートへ追加します。この設定ではスクリプト要素を無効にできないため、コンポーネントがスクリプトを生成する可能性があれば nonce を引き続き渡します。
プロバイダーが提供するのは Base UI のコンテキストです。HTTP ヘッダーを生成または送信せず、アプリケーションのほかの CSP 設定も変更しません。
インストール
Tailwind CSS 4 を設定した React 19 アプリケーションが前提です。UI パッケージをまだインストールしていない場合は、React のピア依存関係とともに追加してください。
pnpm add @tinyrack/ui react react-dom
プロバイダーのサブパスは CSS を追加しません。@tinyrack/ui/core.css と、レンダリングする各コンポーネントのスタイルを引き続き読み込んでください。
レスポンスごとに nonce を渡す
サーバーでレスポンスごとに nonce を 1 回生成してください。style-src-elem は Base UI の <style> 要素を許可し、script-src ディレクティブは同じ nonce が付いた Base UI の <script> 要素を許可します。この最小構成は、アプリケーション全体の CSP に合わせて調整してください。
import { randomBytes } from 'node:crypto';
import type { ReactNode } from 'react';
import { TRCSPProvider } from '@tinyrack/ui/providers/csp';
export function createRequestCsp() {
const nonce = randomBytes(16).toString('base64');
return {
nonce,
header: [
"default-src 'self'",
`style-src-elem 'self' 'nonce-${nonce}'`,
`script-src 'self' 'nonce-${nonce}'`,
].join('; '),
};
}
export function AppProviders({
children,
nonce,
}: {
children: ReactNode;
nonce: string;
}) {
return <TRCSPProvider nonce={nonce}>{children}</TRCSPProvider>;
}
返された header をそのレスポンスに設定し、サーバーでレンダリングするプロバイダーに nonce を渡してから、ハイドレーションにも同じ値をシリアライズしてください。ブラウザーで別の nonce を生成しないでください。style-src-elem がある場合、スタイル要素は style-src とは別に制御されます。
生成されるスタイル要素を無効にする
ポリシーでインラインのスタイル要素を許可しない場合は、明示的に無効にしてください。disableStyleElements は Base UI のスクリプト要素を抑止しないため、レスポンスごとの nonce も引き続き渡します。
import type { ReactNode } from 'react';
import { TRCSPProvider } from '@tinyrack/ui/providers/csp';
export function AppProviders({
children,
nonce,
}: {
children: ReactNode;
nonce: string;
}) {
return (
<TRCSPProvider disableStyleElements nonce={nonce}>
{children}
</TRCSPProvider>
);
}
次に、ポリシーで許可した静的スタイルシートへ、次の補助規則をそのまま追加します。
.base-ui-disable-scrollbar {
scrollbar-width: none;
}
.base-ui-disable-scrollbar::-webkit-scrollbar {
display: none;
}
現在 Tinyrack が使用する Base UI では、Scroll Area が Viewport にこのクラスを適用し、ネイティブのスクロールバーを隠してカスタムスクロールバーを表示します。アプリケーションで Scroll Area をレンダリングする場合は、静的規則を維持してください。Tinyrack Select はトリガー基準の配置を使用し、Base UI の項目整列配置モードを使用しません。
適用範囲を理解する
disableStyleElements が抑止するのは、Base UI の CSP コンテキストを通して生成されるスタイル要素だけです。Tinyrack、Base UI、アプリケーションコードが生成するインラインの style 属性は削除しません。この属性は style-src-attr などのディレクティブで別に制御されるため、アプリケーションのポリシーで扱いを決めてください。
プロバイダーは、アプリケーションが生成するその他の要素、フレームワークのスクリプト、サードパーティのタグ、スタイルシートに nonce を追加しません。これらのリソースには、フレームワークの CSP 連携を引き続き使用してください。基盤となる動作は Base UI CSP Provider のドキュメントで確認できます。
API
TRCSPProvider と TRCSPProviderProps は @tinyrack/ui/providers/csp からインポートしてください。
| プロパティ | 型と既定値 | 役割 |
|---|---|---|
children | ReactNode | 子孫の Base UI コンポーネントに CSP の値を提供します。 |
nonce | string、既定値なし | Base UI が生成する <style> と <script> 要素に、リクエストの nonce を追加します。 |
disableStyleElements | boolean、既定値は false | Base UI のスタイル要素をレンダリングしません。スクリプトには影響せず、アプリケーション側で同等の CSS を提供する必要があります。 |
ポリシーを検証する
ローカルの開発画面だけで判断せず、本番レスポンスを検査してください。
- レスポンスに意図した CSP ヘッダーがあり、その nonce がレンダリングされた Base UI 要素の値と一致することを確認します。
- 同じ nonce でハイドレーションし、ブラウザーコンソールまたは CSP のレポート送信先に違反がないことを確認します。
- スタイル要素を無効にした場合は、Scroll Area と項目をトリガーに揃える設定を有効にした Select を開き、Popup または List のネイティブスクロールバーが隠れ、カスタムスクロールが動作することを確認します。
- キーボードとタッチ操作でオーバーレイとスクロールロックを動かし、ポリシー適用下でも動作することを確認します。