# Kuroco Security Audit

> Kurocoサイトのセキュリティ設定を Admin MCP 経由で読み取り、チェックリストに照らしてリスクを診断・報告する読み取り専用スキル。設定の変更は一切行わない。APIセキュリティ方式・CORS・IPアドレス制限・ログイン/パスワードポリシー・2要素認証（ワンタイムパスワード）・権限グループとスーパーユーザー一覧・静的アクセストークン/シークレットの棚卸し・公開されているAPI・監査ログを対象とする。「セキュリティチェック」「セキュリティ監査・診断・レビュー」「設定の棚卸し」「security audit」「CORS/IP制限/権限を確認」「セキュリティチェックシート」「脆弱性が心配」など、Kurocoの設定が安全か点検・報告する依頼で使用。

- Skill: `diverta/kuroco-security-audit` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add diverta/kuroco-security-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/diverta/kuroco-security-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: diverta (https://skillmd.com/u/diverta)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/diverta/kuroco-security-audit

---


# Kuroco セキュリティ設定チェック Skill（Admin MCP）

## 概要

Admin MCP の**読み取り系ツールのみ**でKurocoサイトの設定を収集し、
[references/checklist.md](references/checklist.md) の基準に照らして所見をまとめる。

| 本スキルの範囲 | 範囲外 |
|--------------|-------|
| 管理画面で設定できる項目の設定値レビュー（設定ミス・過剰権限・弱いポリシーの検出） | 脆弱性スキャン／ペネトレーションテスト（VAddy等の外部サービスを案内する） |
| 設定値と推奨値の突き合わせ、リスクの重大度付け、対処方針の提示 | 設定の修正（**本スキルでは行わない**。修正は `/kuroco-admin-mcp` に切り替え、ユーザー承認のうえ実施） |
| MCP で取得できない項目の「手動確認リスト」化 | Kurocoプラットフォーム自体の安全性評価（→ kuroco-docs `about/security.md`） |

> **最小フロー（通常 3〜6 tool call）:**
> 1. 監査スコープの合意（対象サイト・確認カテゴリ・レポート形式）
> 2. 利用可能な読み取りツールの把握
> 3. 設定値の収集（読み取り専用・並列可）
> 4. チェックリストで判定 → レポート

---

## 前提: 接続

Admin MCP の接続・認証・スコープ付きURLの仕様は `/kuroco-admin-mcp` を参照。本スキルでは以下だけ守る。

- **`/readonly` 付きのスコープURLを推奨する。** 書き込み系ツールが一覧に出ないため、事故が構造的に防げる
  ```
  https://{site}.g.kuroco.app/direct/rcms_api/admin_mcp/x/all/readonly
  ```
- 監査は横断的にモジュールを見るため、スコープは `all` が適切なことが多い。`/readonly` と併用する
- 接続済みサーバが書き込み可能なスコープ（`/x/all` など）の場合でも、**本スキル実行中は読み取り系ツールしか呼ばない**

---

## 手順

### Step 1: 監査スコープの合意

実行前にユーザーへ確認する（推測で始めない）:

1. **対象サイト** — 接続済みAdmin MCPサーバが複数ある場合はどれか。本番／ステージングの別
2. **確認カテゴリ** — 全カテゴリか、特定カテゴリ（例: 公開APIまわりだけ）か
3. **サイトの前提** — 「完全公開のメディアサイト」「会員限定サイト」「社内利用」で妥当な設定は変わる。判定の基準になるため必ず聞く
4. **レポートの出力先** — チャット上のみか、ファイル保存か（保存はユーザーの明示的な同意を得てから。[セキュリティ注意事項](#セキュリティ注意事項)参照）

**ユーザーに聞けない場合（非対話実行・`AskUserQuestion` が使えない等）は、監査を止めない。** 次の順で埋め、埋めた内容をレポート冒頭に「仮定（未確認）」として列挙する:

| 項目 | 埋め方 |
|------|--------|
| 対象サイト | `whoami` の `site`（`site_key` / `env` / 各URL）を採用する。**推測しない** |
| 確認カテゴリ | 依頼文から読み取る。限定の指示がなければ全カテゴリ |
| サイトの前提 | 依頼文の記述を最優先で採用する（例:「会員限定のコンテンツを持つ」）。手がかりが無い場合は**判定を「要検討」に寄せ、前提ごとに結論が変わる項目を明示する**。前提を推測して「要対処」と断定しない |
| レポートの出力先 | チャット出力のみ。**同意なしにファイル保存しない** |

### Step 1.5: `whoami` で接続コンテキストを確定する

**最初に呼ぶツールは `whoami`。** 引数なしで、1コールでチェックリストの複数カテゴリを一次情報として埋められる。

| `whoami` の返却 | 使いどころ |
|----------------|-----------|
| `site`（`site_id` / `site_key` / `env` / `site_url` / `api_url` / `mng_url` / `edge_url`） | **対象サイトの取り違え検出**。Step 1 の「対象サイト」の確定。フロントとAPIのドメイン一致（Cookie認証の妥当性）判定 |
| `security.ip_restrictions` | **IPアドレス制限のカテゴリはここで確定する。** `management`（管理画面）/ `admin_mcp`（Admin MCP専用リスト）/ `files`（KurocoFiles の allowlist・denylist）それぞれの `enabled` / `mode` / `current_ip_allowed` / `rules` |
| `member.super_flg` / `member.groups` | スーパーユーザー権限の棚卸しの起点（**実行者自身**が該当するかを含む） |
| `permissions.granted` / `denied` / `approval_required` | 実行アカウントの権限。取得できた／できなかったの切り分け根拠にする |
| `permissions.connection.scope` / `readonly` | 監査に使っている接続の性質。レポートの「使用した接続」欄に書く |
| `request.client_ip` | IP制限の判定に使う接続元 |

> `security.ip_restrictions` の `rules`（設定内容そのもの）は、サイト設定を更新できる接続でのみ返る。返らなかった場合は `enabled` までを事実として報告し、`rules` は「手動確認」に回す。

### Step 2: 利用可能な読み取りツールの把握

MCPクライアントが接続時に取得済みのツール一覧を確認する。**MCPツール以外の経路（curl での REST 呼び出し・管理画面のブラウザ操作・シェル）は使わない** — MCP の権限・承認・監査ログを迂回するため。見えているツールで届かない項目は Step 4 の「手動確認」に回す。

チェックリストの各カテゴリを、一覧に**実在するツール名**へ対応づける。

- **ツール名を推測して呼ばない。** 一覧に見えている名前が正
- 対応する読み取りツールが見つからない項目は、その場で諦めず Step 4 で**手動確認項目**として扱う（チェックリストに管理画面上の場所を記載してある）
- レコード数ゼロのモジュールでは読み取り系ツールが一覧から除外される仕様のため、「ツールが無い＝設定が存在しない」ではない

### Step 3: 設定値の収集

- **読み取り系ツールのみ**を使う。`create` / `update` / `delete` / `bulk_*` は本スキルでは一切呼ばない
- 独立した読み取りは複数のtool callを同時に発行して並列実行してよい
- 一覧取得は `cnt` で件数を制限する。件数が知りたいだけの場合は `cnt` を小さくし `pageInfo.totalCnt` を見る。`cnt` / `columns` を持たないツールもあるので、呼ぶ前に inputSchema で確認する
- 取得できたレスポンスの**実フィールド名と実値**だけを根拠にする。値が取れなかった項目を「設定済み」「未設定」と断定しない
- **キーがレスポンスに存在しないことを「無効」「未設定」と読み替えない。** 真偽値の設定を判定するときは、`false` / `0` が**明示的に返っている**ことを確認する。キー自体が無い場合は取得できなかった（＝手動確認）
- **A7（未使用API／エンドポイント）は設定値ではなく利用実績で判定する。** `api-list` → `api_uri-list`（直近8日間）、より長い窓は `api_analytics-list`（→ checklist の [A7 の裏取り](references/checklist.md#a7-の裏取り使用中かどうかの判定)）
- **何らかの理由で取得できなかったとき、黙ってチェック項目を落とさない。** レスポンスが大きすぎて読めない、ツールが見えない、値が返らない——理由は何であれ、そのために確認できなくなった項目を**「手動確認」に列挙し、理由を書く**。カバレッジが落ちたことを隠すと、監査結果が実態より安全に見える

### Step 4: チェックリストによる判定

[references/checklist.md](references/checklist.md) の各項目について、次のいずれかに分類する:

| 判定 | 意味 |
|------|------|
| **要対処** | 設定値を確認し、Step 1 で聞いたサイト前提に照らして問題がある |
| **要検討** | 設定値を確認したが、妥当性が運用方針に依存する（判断材料を添えて提示） |
| **問題なし** | 設定値を確認し、推奨に沿っている |
| **手動確認** | MCPから設定値を取得できなかった。管理画面での確認手順を案内する |

重大度はチェックリストの既定値を出発点とし、**サイト前提で調整する**（例: 完全公開のメディアサイトで
「APIセキュリティ＝なし」は既定 HIGH だが、公開データ専用APIと確認できれば「問題なし」に下げてよい）。
調整した場合は理由をレポートに書く。

### Step 5: レポート

[references/report-format.md](references/report-format.md) の形式で報告する。最低限、以下を含める。

- 対象サイト・実施日時・スコープ・使用した接続（`/readonly` か否か）
- 重大度順の指摘一覧（現在値・推奨値・根拠となった取得元ツール・対処方針）
- **手動確認が必要な項目の一覧**（取得できなかったことを隠さない）
- **設定変更を一切行っていない旨の明記**

---

## 重要なルール

| ルール | 説明 |
|--------|------|
| **読み取り専用** | 本スキル実行中は書き込み系ツールを呼ばない。修正依頼を受けたら `/kuroco-admin-mcp` に切り替え、改めて実行前確認を取る |
| **推測で埋めない** | 取得できなかった設定値は「手動確認」。デフォルト値を仮定して「問題なし」と書かない |
| **サイト前提で判定** | 妥当な設定は用途で変わる。前提を聞かずに一律で「危険」と断定しない |
| **秘密情報を出力しない** | トークン・シークレット・パスワードの**実値は一切レポートに書かない**（存在・件数・有効期限・更新日時のみ） |
| **件数制限** | 一覧取得は `cnt` を指定する。全件ダンプしない |
| **課金意識** | 同じ情報を重複取得しない。**ただし課金を理由にチェック項目や再監査を省かない**——網羅性が優先 |
| **網羅性を偽らない** | チェックリストは既知の設定項目のカバーであり、サイト固有の実装リスク（前後処理・カスタム関数・バッチ）は対象外である旨をレポートに明記する |

---

## エラーハンドリング

接続・認証まわり（`400` / `401` / `403` / ツール拒否）の原因と対処は `/kuroco-admin-mcp` の
エラーハンドリング節と同一。本スキル固有の扱いは以下。

| 症状 | 対処 |
|------|------|
| 一部モジュールのツールだけ見えない | スコープ不足の可能性。監査に必要なモジュール名を挙げて、`/x/all/readonly` での再登録を提案する。**見えない項目は「手動確認」として残し、監査を続行する** |
| 監査の途中で認証切れ | 即座に停止し、どのカテゴリまで収集済みかを報告する。再認可後は未収集のカテゴリから再開する（収集済みの読み取りを取り直さない＝課金削減） |
| 権限不足で特定の一覧が空 | 「0件」と「権限で見えていない」を区別できない場合がある。区別できないときは断定せず、実行ユーザーの権限を添えて事実を報告する |
| ログ系ツールが `list` / `pageInfo` キーごと返ってこない | **これを「0件」と読まない。** 正常な0件は `{"list": [], "pageInfo": {...}}` の形で返る。`list` キー自体が無い応答は取得できなかったものとして「手動確認」に回す |

---

## セキュリティ注意事項

- **トークン・シークレット・パスワードの実値を表示・ログ出力・ファイル保存しない。** 静的アクセストークンや自動ログイントークンの一覧を取得した場合も、報告するのは件数・有効期限・作成日時までにとどめる
- **レポートのファイル保存はユーザーの明示的な同意を得てから。** セキュリティ監査結果は「どこが弱いか」の一覧そのものであり、漏洩時の影響が大きい。会員データやIPアドレスなど個人情報を含む場合は、保存範囲を提示して確認する
- **メンバー一覧・ログイン履歴の取得は必要最小限に。** 権限棚卸しに必要なのは通常「ユーザー種別」「有効/無効」「所属グループ」であり、個人情報カラムまで取得する必要はない
  - **`columns` を省略すると全カラムが返る。** メンバー系・ログイン履歴系のツールは、氏名・メールアドレスを含んだ状態で返ってくる。一度取得してしまえばレポートに書かなくても取得の事実は残るので、**`columns` を指定してから呼ぶ**（例: `member-list` なら `member_id` / `group_ids` / `login_ok_flg`）
  - `columns` に指定できる名前が分からない場合は、**まず存在しない名前を1つ渡してエラーを出させ、返るメッセージから有効なカラム名を得る。** 個人情報を取得してから絞るのではなく、絞ってから取得する
- 監査自体が管理操作ログに記録される。共有環境では実施をチーム内に周知するようユーザーに勧める

---

## アンチパターン

| やりがち | 問題 | 推奨 |
|---------|------|------|
| 監査のついでに設定を直す | 承認なき変更。監査の独立性も損なう | 本スキルは報告まで。修正は `/kuroco-admin-mcp` で別途承認を取る |
| 取れなかった項目を省く | 未確認が「問題なし」に見え、監査結果が実態より安全に見える | 「手動確認」として明示的に列挙する |
| デフォルト値を前提に判定 | 実際の設定と乖離した誤報告 | 取得できた実値のみを根拠にする |
| サイト前提を聞かずに一律判定 | 公開メディアサイトに会員サイトの基準を当てて誤検知を量産する | Step 1 で用途を確認してから判定 |
| トークン値をレポートに貼る | 監査レポートが漏洩経路になる | 実値は書かない |
| `cnt` なしでメンバー全件取得 | レスポンス肥大・不要な個人情報の取得 | `cnt` で制限し、`pageInfo.totalCnt` で件数を見る |
| 名前や実績ゼロだけで「未使用API」と断定する | 稼働中APIの無効化提案になる（発行済みトークンの削除を伴う）。月次バッチ・障害時のみの導線は窓に現れない | 実績で裏取りし、確認した窓の長さを添えて「要検討」で出す |
| 「セキュリティ上問題ありません」と締める | チェックリスト外のリスク（カスタム処理・運用）を保証したことになる | 「本チェックリストの範囲では」と範囲を明示する |

---

## 他スキルとの連携

| スキル | 用途 | 使い分け |
|--------|------|----------|
| `/kuroco-admin-mcp` | Admin MCP の接続・認証・ツール探索、および**設定の修正** | 本スキルの前提。指摘事項を実際に直すときはこちら |
| `/kuroco-api-content` | API認証方式（Cookie/Token/StaticToken）・CORSの設計 | 「どう直すべきか」の設計判断 |
| `/kuroco-docs` | 各設定項目の公式ドキュメント | 指摘の根拠URLを添えるとき |
| `/kuroco-frontend-integration` | KurocoFront の Basic認証・デプロイ設定 | フロントエンド側の指摘の対処 |

