Skip to content

半公開キー(kudaq_)と ?key= クエリレーンを追加(型で footgun 防止) - #25

Merged
kojira merged 2 commits into
mainfrom
claude/esp32-api-version-rcx3x3
Jul 20, 2026
Merged

半公開キー(kudaq_)と ?key= クエリレーンを追加(型で footgun 防止)#25
kojira merged 2 commits into
mainfrom
claude/esp32-api-version-rcx3x3

Conversation

@kojira

@kojira kojira commented Jul 20, 2026

Copy link
Copy Markdown
Member

背景

ヘッダを付けられないクライアント(素の GET しか打てないフェッチ、URL 一本の共有、簡易 IoT)
向けに、外部エージェントから /drop?key= 認証追加の要望があった。CLAUDE.md は従来
?key= 禁止」だったが、脅威モデルを実環境で評価し直し、「文書で祈る」でなく「型で統治する」
強化版
で受け入れる(オーナー判断でルール改訂)。

設計: 半公開キー kudaq_ による二層化

  • 正規レーン(推奨・従来どおり): Authorization: Bearer。通常鍵 kuda_・半公開鍵
    kudaq_ どちらも可。
  • 互換レーン(新規): ?key=kudaq_...半公開キー種のみ受理。通常鍵 kuda_
    ?key= に貼っても 401(isQueryKey/looksLikeApiKey)。ヘッダとクエリ併用はヘッダ優先
  • kudaq_kuda_ で始まらない(5文字目が q vs _)ので両種は明確に分離。ハッシュ照合
    なので、種は発行時に平文へ焼き込まれ DB カラム追加は不要。

これにより「利用者が自分の本キーを URL に貼る」footgun をコードで防ぐ。

端点でのURL残留を潰す(原提案への強化)

  1. observability.logs.invocation_logs = false — Cloudflare の呼び出しログには
    リクエスト URL(=?key= 平文)が載る。これを無効化(console.* ログは維持)。
    ※原提案は「観測ログにURLは残らない」と誤認していたが、本 repo は observability 有効。
  2. 全応答に Referrer-Policy: no-referrerutil.tsjson()//app.js)。
  3. 既存の Cache-Control: no-store
  4. 自前でURLをログする場合のマスク関数 redactKeyInUrlkey=kuda_***、grep 可)。
    現状コードは URL を一切ログしていないことも確認済み。

スコープ(non-negotiable を維持)

  • /ingest/api/admin/* はクエリキー不可(ヘッダ/セッション必須。今後も追加しない)。
  • 漏えい時の最大被害は read-only /drop・当該キーの日次クォータ分のみ。台帳に全消費が残り、
    ダッシュボードからワンクリック無効化。

UI / ドキュメント

  • 発行フォームに「半公開キー(URL利用可・低クォータ)として発行」チェックボックス、キー一覧に
    種別バッジ(通常 / 半公開(URL可))、注記。/api/keysquery_allowed を受け付け。
  • README に2レーンと脅威モデルの根拠、CLAUDE.md のルールを改訂。

検証

  • pnpm run typecheck
  • pnpm test(vitest ユニット 58件kudaq_ 生成・種判定・redactKeyInUrl 追加)✅
  • pnpm run test:e2e(wrangler dev + 管理者、68/68 pass)✅
    • ?key=<kudaq>→200 / 通常鍵を?key=→401(平文非露出)/ 不明kudaq_→401 /
      ヘッダ優先で記帳 / /dropno-referrer / /ingest?key=→401 / /api/admin/*?key=→403。
  • observability.logs.invocation_logs:false は wrangler スキーマ検証を通過(dev 起動で確認)。

🤖 Generated with Claude Code

https://claude.ai/code/session_013biLJzQnwKk8xnMjrJD7cS


Generated by Claude Code

ヘッダを付けられないクライアント向けに /drop の ?key= 認証を条件付きで受理する。
セキュリティは「文書で祈る」でなく「型で統治する」方式:

- 別種の半公開キー kudaq_ を導入(auth.ts)。?key= はこの種のみ受理し、通常鍵
  kuda_ を URL に貼っても 401(isQueryKey/looksLikeApiKey)。ヘッダとクエリ併用は
  ヘッダ優先。/ingest・/api/admin/* はクエリキー不可のまま。
- 端点でのURL残留を潰す: observability.logs.invocation_logs=false(呼び出しログに
  URLが載るのを止める。console.* ログは維持)、全応答 Referrer-Policy: no-referrer、
  既存の Cache-Control: no-store。ログ用マスク redactKeyInUrl(key=kuda_***)。
- 発行UI: 「半公開キー(URL利用可)」チェックボックス、一覧に種別バッジ、注記。
  /api/keys は query_allowed を受け付け kudaq_ を発行。
- CLAUDE.md の「?key= 禁止」を「?key= は kudaq_ 種のみ受理」に改訂(根拠つき)。
  README に2レーンと脅威モデルの根拠を明記。
- テスト: auth.test に kudaq_ 生成・種判定・redact。e2e に ?key= 受理/通常鍵拒否/
  不明キー401/ヘッダ優先/no-referrer/ingest・admin のクエリ不可(68/68)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013biLJzQnwKk8xnMjrJD7cS
@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
kuda 3f87d07 Jul 20 2026, 05:47 PM

@kojira
kojira merged commit 4117918 into main Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants