From 6153fd880abeea8d09de4f4ec1e9492a4efe44a2 Mon Sep 17 00:00:00 2001 From: nrslib <38722970+nrslib@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:25:27 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=BB=E3=82=AD=E3=83=A5=E3=83=AA=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=8A=E3=83=AC=E3=83=83=E3=82=B8=E3=81=AB=E3=83=9E?= =?UTF-8?q?=E3=83=AB=E3=83=81=E3=83=86=E3=83=8A=E3=83=B3=E3=83=88=E3=83=87?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E5=88=86=E9=9B=A2=E3=82=BB=E3=82=AF=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- builtins/en/knowledge/security.md | 40 +++++++++++++++++++++++++++++++ builtins/ja/knowledge/security.md | 40 +++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/builtins/en/knowledge/security.md b/builtins/en/knowledge/security.md index 6c9d844..de2b945 100644 --- a/builtins/en/knowledge/security.md +++ b/builtins/en/knowledge/security.md @@ -148,6 +148,46 @@ if (!safePath.startsWith(path.resolve(baseDir))) { - Resource exhaustion attack possibility → Warning - Infinite loop possibility → REJECT +## Multi-Tenant Data Isolation + +Prevent data access across tenant boundaries. Authorization (who can operate) and scoping (which tenant's data) are separate concerns. + +| Criteria | Verdict | +|----------|---------| +| Reads are tenant-scoped but writes are not | REJECT | +| Write operations use client-provided tenant ID | REJECT | +| Endpoint using tenant resolver has no authorization control | REJECT | +| Some paths in role-based branching don't account for tenant resolution | REJECT | + +### Read-Write Consistency + +Apply tenant scoping to both reads and writes. Scoping only one side creates a state where data cannot be viewed but can be modified. + +When adding a tenant filter to reads, always add tenant verification to corresponding writes. + +### Write-Side Tenant Verification + +For write operations, use the tenant ID resolved from the authenticated user, not from the request body. + +```kotlin +// NG - Trusting client-provided tenant ID +fun create(request: CreateRequest) { + service.create(request.tenantId, request.data) +} + +// OK - Resolve tenant from authentication +fun create(request: CreateRequest) { + val tenantId = tenantResolver.resolve() + service.create(tenantId, request.data) +} +``` + +### Authorization-Resolver Alignment + +When a tenant resolver assumes a specific role (e.g., staff), the endpoint must have corresponding authorization controls. Without authorization, unexpected roles can access the endpoint and cause the resolver to fail. + +For endpoints with role-based branching, verify that tenant resolution succeeds on all paths. + ## OWASP Top 10 Checklist | Category | Check Items | diff --git a/builtins/ja/knowledge/security.md b/builtins/ja/knowledge/security.md index 14ab513..1e5d91a 100644 --- a/builtins/ja/knowledge/security.md +++ b/builtins/ja/knowledge/security.md @@ -148,6 +148,46 @@ if (!safePath.startsWith(path.resolve(baseDir))) { - リソース枯渇攻撃の可能性 → 警告 - 無限ループの可能性 → REJECT +## マルチテナントデータ分離 + +テナント境界を超えたデータアクセスを防ぐ。認可(誰が操作できるか)とスコーピング(どのテナントのデータか)は別の関心事。 + +| 基準 | 判定 | +|------|------| +| 読み取りはテナントスコープだが書き込みはスコープなし | REJECT | +| 書き込み操作でクライアント提供のテナントIDを使用 | REJECT | +| テナントリゾルバーを使うエンドポイントに認可制御がない | REJECT | +| ロール分岐の一部パスでテナント解決が未考慮 | REJECT | + +### 読み書きの一貫性 + +テナントスコーピングは読み取りと書き込みの両方に適用する。片方だけでは、参照できないが変更できる状態が生まれる。 + +読み取りにテナントフィルタを追加したら、対応する書き込みも必ずテナント検証する。 + +### 書き込みのテナント検証 + +書き込み操作では、リクエストボディのテナントIDではなく認証済みユーザーから解決したテナントIDを使う。 + +```kotlin +// NG - クライアント提供のテナントIDを信頼 +fun create(request: CreateRequest) { + service.create(request.tenantId, request.data) +} + +// OK - 認証情報からテナントを解決 +fun create(request: CreateRequest) { + val tenantId = tenantResolver.resolve() + service.create(tenantId, request.data) +} +``` + +### 認可とリゾルバーの整合性 + +テナントリゾルバーが特定ロール(例: スタッフ)を前提とする場合、エンドポイントに対応する認可制御が必要。認可なしだと、前提外のロールがアクセスしてリゾルバーが失敗する。 + +ロール分岐があるエンドポイントでは、全パスでテナント解決が成功するか検証する。 + ## OWASP Top 10 チェックリスト | カテゴリ | 確認事項 |