Skip to content
Merged
7 changes: 4 additions & 3 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -1397,9 +1397,9 @@ SQL のプレースホルダにJSON形式のパラメータを埋め込み、人
- 適用した変換ステップの表示
- Response/AuthnRequest のサマリと定番チェックリスト(Response のみ)
- Assertion ごとの構造表示(NameID・属性テーブル・Conditions・AuthnStatement・SubjectConfirmationData)
- 整形済み生 XML の折りたたみ表示 + `CopyButton`
- 整形済み生 XML の折りたたみ表示 + `CopyButton`。「生 XML」/「マスク XML(共有用)」の `ToggleGroup` 切替に対応し、マスク XML は `maskSamlXml` で NameID・全 AttributeValue を値ベース一貫トークン化 + `secret-scrubber`(`HIGH_ENTROPY` 除外)で URL 埋め込みメール等を除去した PII 削減版を表示・コピーできる

**モジュール構成:** `src/utils/saml/`(`types.ts` 型定義 / `decode.ts` 自動判定デコードチェーン / `parse.ts` XML → 構造化モデル / `checks.ts` 定番チェックリスト / `format.ts` XML 整形 / `index.ts`)/ `src/components/tools/SamlDecoder.tsx` / `src/pages/tools/saml-decoder.astro`
**モジュール構成:** `src/utils/saml/`(`types.ts` 型定義 / `decode.ts` 自動判定デコードチェーン / `parse.ts` XML → 構造化モデル / `checks.ts` 定番チェックリスト / `format.ts` XML 整形 / `mask.ts` 共有用マスク出力 / `index.ts`)/ `src/components/tools/SamlDecoder.tsx` / `src/pages/tools/saml-decoder.astro`

**追加依存:** `fflate`(raw deflate 展開)。

Expand All @@ -1408,8 +1408,9 @@ SQL のプレースホルダにJSON形式のパラメータを埋め込み、人
- XMLDSig 署名検証・`EncryptedAssertion` の復号・LogoutRequest/LogoutResponse 等の他メッセージ型は非対応(署名・暗号化は存在の有無のみ表示)
- ブラウザの `DOMParser` は外部エンティティを解決しないため XXE は発生しない
- 全処理はブラウザ内で完結し、入力(Assertion に含まれる PII を含む)を外部サーバーに送信しない
- 「共有用マスク XML」は構造上の PII フィールドと `secret-scrubber` の既知パターンの除去であり、完全な匿名化を保証しない(共有前の目視確認が必要)

**スコープ外(v1):** XMLDSig 署名検証(C14N 実装)・EncryptedAssertion 復号・LogoutRequest/LogoutResponse 等の他メッセージ型・共有用マスク出力(secret-scrubber 連携)
**スコープ外(v1):** XMLDSig 署名検証(C14N 実装)・EncryptedAssertion 復号・LogoutRequest/LogoutResponse 等の他メッセージ型

---

Expand Down
33 changes: 33 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4663,3 +4663,36 @@ XMLDSig 署名検証は C14N(正規化)の実装コストが大きく、初
- ✅ 追加依存は `fflate` のみ。型定義同梱でパッケージ追加が最小限
- ✅ zlib ラッパー付き実装の IdP にも `decompressSync` の自動判定で耐性がある
- ⚠️ 署名検証・復号非対応のため、SAMLデコーダの出力はあくまで「中身の確認・トラブルシュート用」であり、正当性の証明には使えない(UI 上に非対応を明記)

---

## [125] SAMLデコーダ: 共有用マスク出力は構造ベースを主・secret-scrubber を副で併用

**2026-07-20 | ステータス: 採用**

### 背景

SAMLデコーダのデコード結果 XML には NameID や属性値として社員の氏名・メールアドレス等の PII が含まれる。issue #745 で、Slack や issue コメント等への貼り付け共有を想定した「PII を除去した共有用マスク XML」の出力機能が要求された。

マスク方式として、既存の `secret-scrubber`(パターンベースの正規表現マッチ)をそのまま適用する案と、SAML の構造(NameID・AttributeValue 要素)を対象に置換する案があった。

### 決断

**構造ベース(NameID/AttributeValue のテキスト置換)を主、`secret-scrubber` を副で併用する二段構えを採用する。** `secret-scrubber` は `HIGH_ENTROPY` カテゴリを除外して適用する。

- フェーズ1(構造ベース): 再パースした DOM 上で `saml:NameID` / `saml:AttributeValue` のテキストを値ベース一貫トークン `[REDACTED:PII_n]` に置換する。同一値は同一トークンにすることで NameID とマッチする属性値(例: `mail` 属性)の相関を保つ。
- フェーズ2(scrubber 併用): 再シリアライズ後の文字列に `scrubText` を適用し、`Destination` の URL クエリに埋め込まれたメールアドレス等、構造では拾えない残余を救済する。

理由: `secret-scrubber` 単独(パターンベースのみ)では正規表現で拾えない日本語氏名(例: `displayName` 属性の「山田 太郎」)等の意味的 PII を検出できない。逆に `HIGH_ENTROPY` を有効にしたまま適用すると、`ds:SignatureValue` / `ds:X509Certificate` の base64(非 PII・公開情報)を over-mask してしまう。SAML の構造を理解した上で意味的 PII フィールドを確実に除去しつつ、URL 埋め込み等の構造外の残余を scrubber で補完する二段構えが最も過不足が少ない。

### 却下した選択肢

- **`secret-scrubber` 単独適用(`HIGH_ENTROPY` 込み)**: 日本語氏名等パターンで拾えない PII を見逃す一方、署名値・証明書の base64 を過剰にマスクし、共有先での有効性確認(署名有無の目視)を妨げる
- **完全な匿名化の保証**: XML の構造は無限に多様であり、独自拡張属性やカスタムスキーマまで含めた完全網羅は非現実的。UI 上に「共有前に必ず目視で確認」の注記を出し、過信を防ぐ設計とした

### 結果・トレードオフ

- ✅ 意味的 PII(NameID・全属性値)を構造的に確実に除去できる
- ✅ 署名値・証明書等の非 PII base64 を over-mask しない
- ✅ 値ベース一貫トークンにより NameID とメール属性等の相関が UI 上で確認できる
- ⚠️ 構造外(要素名・属性名自体に PII が含まれる等の非定型なケース)は対象外。完全な匿名化は保証しない
Loading