クォータ/レート制限の check-then-act は TOCTOU で並行突破される
セキュリティ
並行処理
設計判断
「現在の使用回数を COUNT して上限未満なら通す → 後で使用を記録する」という実装は、判定(read)と記録(write)が原子的でないため、上限境界で同時に来た複数リクエストが全て同じ COUNT を読んで全て通過し、上限を超過できる(TOCTOU)。記録を非同期(fire-and-forget)にしているとさらに窓が広がる。
判断基準・対策
- レート制限/クォータが DoS やコスト抑制の主防御なら、判定と記録を原子的にする。例: 使用回数の INSERT を同期化し
INSERT ... RETURNINGで件数を取って上限超過なら拒否、または upsert カウンタで increment-and-check を1文で行う。 - 最低でも記録を同期化(応答前に書く)して最悪の競合窓を潰す。完全な原子化が難しい場合は残存リスクを明示する。
落とし穴
- 「並行数は通常数件だから」と放置すると、攻撃者は意図的に同時バーストを送る。
- 判定のたびに重い問い合わせ(外部 API 含む)をすると、判定自体がボトルネック/コスト源になる。
検証方法
上限境界で同時並行リクエストを送り、許可された数が上限を超えないことを確認する。