確認できなかったときに、通していた:「fail-open」が転売品を招いた話

English version

トレカダッシュ 開発の記録 / 2026年10月

iOS アプリ「トレカダッシュ」で、「Amazon に転売の価格がたくさん入ってきている」という報告が、アプリ内の不具合報告から 3 件届きました。うち 1 件は、¥79,800 の、明らかな転売品でした。原因は、わざと入れていた「確認できなかったら通す」という設計の、盲点でした。HANDOFF とコミット(2026年7月30日)の記録で書きます。

このサイトには、トレカダッシュの作品ページはまだありません。ここに書くのは、開発の記録です。

価格の関門と、「通す」設計

アプリは、通販サイト(楽天市場、Yahoo!ショッピング、Amazon など)の出品を拾って、フィードに出します。そのとき、出品価格が、商品の定価から見て妥当かを調べる「価格の関門」があります。定価を、AI(Web 検索つき)に調べさせて、極端に高い転売品を弾く仕組みです。

この関門には、「定価を確認できなかった場合は、審査せずに通す」という動きがありました。これは意図した設計です。AI が本当に定価を知らない商品を、確認できないだけで除外してしまうと、本物の出品まで消してしまうからです。いわゆる fail-open(失敗したら開く=通す)です。

盲点:検索の上限に達した場合も、同じ道を通っていた

AI の Web 検索には、1 日 300 回の上限があります(想定外の費用を防ぐための回路遮断器)。ところが、関門は、定価を確認できなかった理由を、区別していませんでした。

この二つが、どちらも「定価不明 → 通す」の同じ道を通っていました。前者は意図どおりです。後者は、「調べる前に、道が閉まっていた」だけなのに、関門が、素通しになっていたのです。

穴が、実害になった理由

この穴は、前の変更(Amazon の対象を広げた回)をきっかけに表に出ました。対象を広げたことで、新しく価格を確認する必要がある商品が、一気に増えました。その結果、1 日の上限に、頻繁に達するようになった。上限に達した間は、関門が素通しになって、転売品が大量に混ざりました。

さらに、二次被害がありました。定価が分からなかった結果は、理由を問わず24 時間キャッシュされる設計でした。そのため、一度上限に当たった商品は、上限が解除されたあとも、最大 24 時間、素通しのままになります。

直し方:理由を区別する

専用の目印(QUOTA_EXCEEDED)を作って、二つを区別できるようにしました。

状況関門の動き
AI が本当に定価を知らなかった(null)これまでどおり通す(fail-open のまま)
1 日の上限で、確認自体ができなかった(QUOTA_EXCEEDED)除外する(fail-close)

後者は、24 時間のキャッシュにも入れません。次に呼ばれたときに、あらためて確認を試みます。この関門は、楽天市場、Yahoo!ショッピング、Amazon、AI による出品の発見、楽天ブックスの先着など、価格の審査を使うすべての機能に共通なので、一回の修正が、広い範囲に効きます(コミットの記録では、18 の関数を配備しています)。

報告のあった 3 件は、手作業で非表示にしました。そのあとは、5 分おきに動く再審査のバッチが、同じ見逃しを拾い直す想定です。

確認できていないこと:記録には、「上限のリセット後に、転売価格の報告が来なくなったかを、次のセッションで確認する」と書いてあります。その結果は、この記事を書いた時点で、記録にありません。

ほかの判定にも、同じ穴は無いか

その後の点検(2026年7月30日)で、販売形式の判定や商品の照合など、ほかの AI による判定も確認しました。いずれも、失敗したときは、安全側(除外、または null)に倒れる設計で、新しい fail-open の穴は見つかりませんでした。

分かったこと

「確認できなかった」には、二種類ある。知らなかったのと、調べられなかったのと。

この記事は、HANDOFF(第182回)とコミット(2026年7月30日)の記録から書きました。

この話に出てくるもの

ほかの記録

コメント

感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。

押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。