脅威モデル&OWASP ASVS L1 自己証明
Vaulted が対抗するよう設計された脅威、対象外の脅威、そして業界標準に対するコントロールごとの証明。
バージョン 1.0 · 公開日 2026-04-27 · ソース: main · 作成者: Maxim Novak
このドキュメントについて
これは自己証明であり、第三者による監査ではありません。Vaulted が何を保護すると主張しているか、何を保護しないか、そして各設計上の決定がどのような認められたコントロールに対応するかを正確に確認できるよう存在します。予算が許す時点で独立したレビューを委託し、そのレポートをこのページと並べて公開します。それまでの間、ブラウザの DevTools を使って5分で ゼロ知識の核心的な主張を自分で検証できます。
1. スコープと前提
このモデルは、vaulted.fyiの本番環境デプロイメントを対象とし、Webフロントエンド、APIルート、および Upstash Redis ストレージを含みます。同じ API と通信する範囲で、公開済みの CLI および MCP サーバーも対象に含みます。
スコープ外:
- ユーザーのエンドポイントデバイス(ブラウザ、OS、拡張機能、クリップボード、画面)。
- 共有リンクが配信される通信チャネル(メール、Slack、SMS など)。
- 受信者による平文の事後処理。
- 利用している API サーフェス以下の Vercel または Upstash の脆弱性。
2. 資産と信頼境界
主要資産: 平文のシークレット。これはサーバーに到達してはならず、送信者と受信者のブラウザ外で保持されてはならず、サーバーサイドの状態だけから復元可能であってはならない。
副次的資産: 暗号文、IV、閲覧カウンター、有効期限タイムスタンプ、およびサービスの完全性と可用性。
信頼境界(信頼度の高い順):
- 送信者のブラウザ — 平文と鍵を信頼する。
- 受信者のブラウザ — リンクを開いた後、平文と鍵を信頼する。
- クライアントとサーバー間のネットワーク — 信頼しない;TLS 1.3 と暗号文のみが通過するという設計上の選択で緩和。
- Vaulted サーバー(私たち) — 半信頼。受動的な暗号文ストアとして扱う。脅威モデルは、Vaulted 自体が侵害されても平文が露出しないことを前提とする。
- Upstash Redis — サーバーと同じ信頼レベル。暗号化されたブロブのみ。
3. 脅威アクター
受動的なネットワーク傍受者。 ISP、TLS メタデータにアクセスできるオンパスアクター。TLS と、ネットワーク上に平文や鍵が存在しないことによって対抗。
能動的なネットワーク攻撃者。 MitM 攻撃を試みることができる。TLS、HSTS プリロード、証明書の検証によって対抗。TLS の侵害に成功しても暗号文しか得られない。
侵害されたサーバー・敵対的なオペレーター。 私たち自身を含む。鍵が届かないため、保存されたシークレットを読み取れない。サービスを拒否したり、配信される JS バンドルを変更したりすることはできる — 以下の残存リスクで対処。
有効な共有リンクを持つ未認証の攻撃者。 設計上、完全なリンクを持つ誰でも復号できる。閲覧制限、有効期限、オプションのパスフレーズによってウィンドウを縮小する。これは意図的な特性であり、バグではない。
特定の送信者または受信者を標的にした攻撃者。 エンドポイント、配信チャネル、または受信者による復号後の処理を悪用できる。Vaulted の制御外;誠実さのために文書化。
4. コントロール
- クライアントサイド AES-256-GCM、
crypto.getRandomValuesからのランダムな96ビット IV 使用。 - シークレットごとに
crypto.subtle.generateKeyで生成された256ビット鍵;URL フラグメントに配置し、決して送信しない。 - PBKDF2(高い反復回数)と AES-GCM 鍵ラッピングによるオプションのパスフレーズラッピング。
- Redis
HINCRBYによる原子的な閲覧カウント強制、制限到達時に同一トランザクション内で削除。 - TTL ベースの自動期限切れ、30日を上限;作成後の延長なし。
- 作成と閲覧エンドポイントにおける IP ごとのスライディングウィンドウレート制限。
noindex/s/[id] 閲覧ページで、シークレット URL が検索を通じて漏洩しないよう設定。- TLS 1.3 と HSTS プリロード、安全なセキュリティヘッダー、レート制限ウィンドウを超えた IP ログなし。
5. 残存リスク(対抗していないもの)
これらは意図的な境界の決定であり、Vaulted がユーザーの脅威モデルに適合するかどうかを判断できるよう文書化しています。
- エンドポイントの侵害。 キーロガー、感染したブラウザ、または悪意のある拡張機能は、復号後に DOM から平文を読み取れる。
- 配信チャネルの漏洩。 共有リンクが転送、アーカイブ、または返信メールのスレッドで引用された場合、そのチャネルが攻撃面になる。
- 標的を絞ったバンドルスワップ。 侵害された CDN または Vercel のエッジが特定のユーザーに異なる JS を配信する可能性がある。サブリソース完全性(SRI)と再現可能なビルドは部分的な緩和策であり、ロードマップにある。
- 受信者の行動。 復号後、受信者はコピー、スクリーンショット、または転送できる。
- 弱いパスフレーズ。 使用された場合、弱いパスフレーズはラップされた鍵を持つ誰からでもブルートフォース攻撃を受けられる。
- 物理的な強制・脅迫。 いかなる技術的コントロールのスコープ外。
6. OWASP ASVS L1 自己証明
以下のマトリクスは、Vaulted の実装を選択された OWASP ASVS Level 1 要件に対応付けたものです。適用されないカテゴリ(セッション、認証、ファイルアップロード)は省略せず、N/A と簡潔な理由を付けて記載しています — 項目の欠如が回避と読まれないようにするため。
| ID | カテゴリ | 要件 | 状態 | 根拠 |
|---|---|---|---|---|
| V1.1.1 | アーキテクチャ | アプリケーションの脅威モデリングを含むセキュアな SDLC | Pass | このドキュメント。主要なアーキテクチャ変更のたびにレビュー。 |
| V1.4.1 | アーキテクチャ | 信頼できる強制ポイントがアクセス制御を施行する | Pass | API ルートハンドラーが入力を検証し、src/lib/redis-secrets-store.ts の Redis HINCRBY を介して閲覧を原子的に消費。 |
| V2.10.x | 認証 | サービス・ユーザー認証 | N/A | Vaulted は匿名。ユーザーアカウントなし、サービス間認証なし。認可はシークレット ID と URL フラグメント鍵の知識によって行う。 |
| V3.x | セッション管理 | セッション管理の要件 | N/A | セッションなし、認証状態のための Cookie なし。 |
| V5.1.3 | 入力バリデーション | 信頼されたサービス層での入力バリデーション | Pass | src/app/api/secrets/route.ts での手動ランタイムバリデーション。ペイロード ≤ 1000文字をサーバーサイドで強制;最大閲覧数と TTL を制限。 |
| V5.2.5 | サニタイゼーション | コンテキスト(HTML、JS、URL)に応じた出力エンコーディング | Pass | React はデフォルトですべての補間値をエスケープ。dangerouslySetInnerHTML の呼び出しは、サーバーサイドで型付きデータから構築された JSON-LD リテラルのみをレンダリング。 |
| V6.2.1 | 保存暗号 | 安全なデフォルト値を持つ承認された暗号アルゴリズムの使用 | Pass | Web Crypto API による AES-256-GCM。NIST SP 800-38D。src/lib/crypto.ts 参照。 |
| V6.2.2 | 保存暗号 | 暗号学的に強力な乱数生成 | Pass | IV と鍵材料には crypto.getRandomValues を使用。AES 鍵には crypto.subtle.generateKey を使用。 |
| V6.2.5 | 保存暗号 | 安全でない、または廃止された暗号プリミティブを使用しない | Pass | 暗号パス上のどこにも MD5、SHA-1、DES、RC4、ECB、CBC-without-MAC を使用していない。 |
| V6.3.1 | 保存暗号 | 不正アクセスから保護された鍵 | Pass | 暗号化鍵はサーバーに到達しない。RFC 3986 に従ってクライアントサイドで処理される URL フラグメントにのみ存在。オプションのパスフレーズが共有前に PBKDF2 で鍵をラップ。 |
| V7.1.1 | エラー処理&ログ | ログに機密情報なし | Pass | サーバーはリクエストの形態とレート制限の判断のみをログに記録。相互関連付け可能な形でのシークレット ID なし、暗号文なし、レート制限ウィンドウを超えて保持される IP なし。 |
| V7.4.1 | エラー処理&ログ | 汎用エラーメッセージ | Pass | API ルートは汎用 HTTP ステータスコードと短いエラー文字列を返す。スタックトレースや内部状態の漏洩なし。 |
| V8.1.1 | データ保護 | 機密データの特定と保護 | Pass | サーバーは平文を受け取らない。暗号文は TTL ベースの削除と原子的な閲覧制限強制を伴い、Upstash Redis に暗号化されて保存。 |
| V8.3.1 | データ保護 | URL やリファラーに機密データを露出しない | Pass | 暗号化鍵は URL フラグメントに存在;RFC 3986 §3.5 に基づき、フラグメントはブラウザによってサーバーに送信されず、document.referrer からも除去される。 |
| V9.1.1 | 通信 | すべてのクライアント接続に TLS を使用 | Pass | Vercel エッジで TLS 1.3 を強制。HSTS プリロード済み。HTTP リクエストは HTTPS にリダイレクト。 |
| V10.3.2 | 悪意のあるコード | 悪意のあるコードについてアプリケーションコードをレビュー | Pass | 単一メンテナーのコードベース。すべてのコミットはプロジェクトオーナーが作成;サポートされている場合は署名付きコミット。Dependabot による依存関係の更新はマージ前にレビュー。 |
| V11.1.1 | ビジネスロジック | 乱用からロジックフローを保護 | Pass | Upstash Ratelimit による IP ごとのレート制限(10作成/分、30閲覧/分)。閲覧カウントを原子的にデクリメント。 |
| V12.x | ファイル&リソース | ファイルアップロードと処理の要件 | N/A | Vaulted はファイルアップロードを受け付けない。 |
| V13.2.1 | API&Webサービス | RESTful エンドポイントはリクエストスキーマを検証する | Pass | すべての POST/GET ハンドラーは処理前にパスパラメーター、ボディの形式、Content-Type を検証。 |
| V14.4.3 | 設定 | 標準セキュリティヘッダーの設定 | Pass | HSTS、X-Content-Type-Options、Referrer-Policy、Permissions-Policy を Next.js config で設定。src/proxy.ts の nonce ベースの strict-dynamic script-src でリクエストごとに Content-Security-Policy を強制;API ルートには厳格な default-src none ポリシーを適用。 |
番号付けは ASVS 4.0 の構造に従います。リストは選択的であり、網羅的ではありません — ステートレスでアカウント不要の暗号化暗号文ストアに対して意味のあるコントロールについて正直に示すことが目的です。
7. 変更プロセス
このドキュメントの項目に影響する変更 — 新しいエンドポイント、暗号の変更、依存関係に影響するリファクタリング、インフラの変更 — は、同じ PR でこのページのレビューを必要とします。ドキュメントが更新されると上記のバージョンと公開日がインクリメントされます;以前のバージョンはパブリックな git 履歴でアクセスできます。
サインオフ
この脅威モデルは Vaulted のメンテナーによって誠意を持って公開されています。上記の証明に対するエラー、欠落、異論は歓迎します — [email protected]、または 責任ある開示プログラム.
Maxim Novak — メンテナー、vaulted.fyi · 2026-04-27