解説記事

陳腐化した承認:申請時は正しくても、数時間の承認待ちの後に押された押印は有効か

情報システム部門、基幹システムアーキテクト、および内部監査担当の方へ。AI エージェントの人間承認(Human-in-the-loop)に伴う数時間の離席・待機遅延において、起案から承認、実書き込みまでのデータ乖離(TOCTOU)リスクをどう防ぐかを解説します。

GembaOS は、AI エージェントを職務権限規程・稟議・監査のもとで運用するための実行基盤です。ポリシーによる権限判定、パラメータに紐づくワンタイム許可証、人の承認記録を、オンプレミスまたはプライベート VPC 上で提供します。

この記事で扱うのは、既存の AI エージェント導入において最も見落とされやすい重大なセキュリティホールです。「エージェントがコマンド承認を申請してから、担当者が不在・会議から戻って「Allow(許可)」を押すまでの数時間の時間差(Time-of-Check to Time-of-Use, TOCTOU)」に潜むデータ乖離リスクです。

事故の現場:既存エージェント製品に潜む「盲目的な再開」の罠

水曜日の午前 10:00、カスタマーサポートの AI エージェントが、顧客クレームの対応中に Slack チャンネルまたは開発者 CLI へツール実行の承認通知を起票しました。「注文 #8821 に対する 68,000 円の返金処理を申請します。承認しますか? [Allow / Deny]」。

この午前 10:00 時点でのエージェントの判断根拠は完全に正確でした。CRM 上の記録では返金は未実施であり、顧客のクレーム内容も正当で、社内返金ポリシーに合致していました。

しかし、実際の企業現場において、上長や担当者が 24 時間常に画面に張り付いていることはあり得ません。

正午 12:00、会議を終えて自席に戻った責任者は、Slack に 2 時間前から残っていた通知「エージェントが 68,000 円の返金を申請」を目にします。案件の経緯を思い出し、内容に問題はないと判断して [Allow] をクリックしました。

市場に流通する多くの既存エージェント製品において、まさにこの瞬間に重大インシデントが発生します。 多くのエージェント基盤は、人間による「Allow」のクリックを、単に停止していたワーカープロセスを再開させるためのフラグ(Unpause)としてしか扱いません。ボタンが押された瞬間、エージェントは 2 時間前に生成された古い API ペイロードをそのまま盲目的に外部決済ゲートウェイへ送信します。その結果、店舗ですでに現金返金済みの注文に対して、さらに 68,000 円が二重返金されて直接的な金銭損失を招きます。

この障害は、AI のプロンプトインジェクションやハルシネーションによるものではありません。責任者のビジネス判断も 2 時間前の情報としては妥当であり、エージェントも指定されたツールの範囲内で動いていました。単に**「承認の申請」と「人間の承認」の間に必然的に発生する時間差があり、既存システムが 2 時間前の古いスナップショットを盲信してしまった**のです。

状態乖離のパターン企業の現場で発生する具体例根本原因
不在・会議による放置承認通知が起票され、上長が会議から戻るまでの間に窓口や別担当者が処理を完了させた人間の非同期遅延
手動データ変更承認待ちの間に、別の同僚が注文金額や送付先、ステータスを先行して手動更新した人為的介入の競合
複数エージェントの競合別の自動化プロセスが、同一レコードに対して並行して変更をかけ先に確定させた並行競合
通信タイムアウト決済 API のタイムアウトに伴うリトライ処理が、すでに成功した決済を再送したインフラ再試行

決済 API 自体の保護で防げること、防げないこと

上の事故には決まった反論があります。「決済ゲートウェイには冪等キーと返金上限があるのだから、二重返金にはならない」。正しく、しかし足りません。ゲートウェイが防げるのはゲートウェイ自身に見える二つのことで、事故の原因は見えない三つ目にあります。

保護提供する側防げること防げないこと
リトライの重複排除(冪等キー)決済ゲートウェイなど、機能を持つ APIタイムアウト後に同じ要求が再送される2 時間前に組み立てた要求が、別のキーで二度目として送られる
金額の上限(返金可能残高)決済ゲートウェイ元の決済額を超える返金100,000 円の注文に 45,000 円を二回返金する;店舗で現金返金済みの注文へのカード返金
承認時の前提が今も成り立つか稟議書を持つ呼び出し側だけCRM で完了済み、同僚が金額を変更済み、店舗で現金返金済み—

ゲートウェイが知っているのは「このカード決済にはまだ 68,000 円の返金余地がある」ことだけで、顧客が 10:40 に店舗で現金を受け取ったことは知りません。三つ目の層は、稟議書を持つ側が書き込みの前に CRM と注文記録へ戻って確かめるしかありません。GembaOS は三層すべてを行います。相手が冪等キーを認識するなら相手のキーを使い(キーは GembaOS が稟議 ID と作業票 ID から生成します)、認識しないなら GembaOS 自身が一度だけ送ることを保証します。上限は書き込み前に相手から返金可能額を読んで比べ、相手自身も上限を強制する場合は記録にそう書きます。承認時の前提は書き込み前に項目ごとに読み直して突合します。

「人間の承認済み」は「盲目的な実行許可」ではない

多くのエージェント製品やワークフロー基盤は、「Slack やチケット上で Allow が押された」ことを、そのまま「直ちに API を叩いて書き込んでよい」と同義と捉えています。この二つを混同することが、重大な本番障害を引き起こす原因です。

承認が保証するのは、「その時点のビジネス判断として適切である」という点までです。「今、この実データに対して、1 回だけ安全に書き込んでよい」という実行時の保証は、堅牢なガバナンス実行基盤が担う必要があります。

検証すべき問い人間の承認が答える範囲GembaOS 実行時ゲートが答える範囲
この業務判断は方針として適切か?はい(指名された責任者が署名)—
申請時に見た事実前提は今も変わっていないか?いいえ(会議中に現場が動いた)実行直前の実データベース再照合とアサーション検証
対象レコードは今、安全に書き込める状態か?いいえ排他リースロックとアダプターの同時実行ガード
金額は相手システムのリアルタイム上限内か?いいえ書き込み直前の最新上限値の再取得
処理が確実に 1 回だけ実行されるか?いいえワンタイム許可証とカーネル生成の冪等キー

GembaOS が承認タイムラグの窓をどう狭めるか

GembaOS のアーキテクチャは、**「人間の判断には必然的に非同期な遅延(数分、数時間、あるいは翌朝まで)が伴う」**という現実を起点に設計されています。そのため、GembaOS は承認ボタンを古いデータの無条件な実行トリガーとはみなしません。

[エージェントがツール呼び出しを起票] 
       │ (基幹データのバージョンと前提アサーションを添付)
       ▼
┌──────────────┐      ┌──────────────────────────┐
│  AI が事実を  │ ───> │ 人間の非同期判断(会議・離席)│
│   整理固定   │      │                          │
└──────────────┘      └──────────────────────────┘
                                   │
                              [責任者が承認]
                                   │
                                   ▼
                      ┌──────────────────────────┐
                      │  AI モデルは実行経路から  │
                      │       完全に離脱         │
                      └──────────────────────────┘
                                   │
                                   ▼
                      ┌──────────────────────────┐
                      │ GembaOS ガバナンスカーネル│
                      │ 1. 基幹 DB の現物を再読み込み│
                      │ 2. 前提アサーションの差分検証│
                      │ 3. 許可証の有効期限(TTL)検証│
                      │ 4. 対象レコードの排他ロック   │
                      │ 5. カーネルが一意な冪等キー注入│
                      └──────────────────────────┘
                                   │
                         [現物データと前提が一致]
                                   ▼
                      ┌──────────────────────────┐
                      │  外部 API へ安全に書き込み│
                      └──────────────────────────┘
潜在リスクガバナンスカーネルによる書き込み直前防御
待機中の前提事実の乖離ガバナンスカーネルが直接基幹 DB の最新状態(注文状態、残高、更新日時)を再照合し、承認時のアサーションと突合;差分があれば直ちに中断して許可証を失効させ、作業票に乖離アラートを記録。
許可証の期限切れ承認時に発行されるワンタイム許可証には厳格な有効期間(例:30分)が設定され、期限切れの許可証による誤発火を完全に排除。
並行変更の衝突と上書き相手がバージョンや条件付き書き込みに対応していれば、承認時に読んだバージョンや期待値を書き込みに添え、古ければ相手が拒否;対応していなければ GembaOS が自身経由の書き込みを直列化してリースの中で読み直し、窓のミリ秒数を記録に残す。
予算や利用枠の枯渇実行直前に相手システムから最新の利用上限を再取得し、実数値と突合することで、スナップショットによる枠超過を阻止。
通信断による重複リトライワンタイム許可証は 1 回のみ消費可能;冪等キーはカーネルが生成し、エージェントは指定できない。相手がキーを認識すればリトライは同じ処理に着地;認識しなければタイムアウト後に再送せず、「未確認」として人に回す。

相手の接続先が与える保護の分だけ、GembaOS が引き受けるもの

接続された書き込み操作は、接続先の契約に二つのことを宣言します。リトライが安全か(冪等、キーによる冪等、再試行不可)、そして相手が古い読み取りに基づく書き込みを拒否できるか(バージョン、条件付き書き込み、何もない)。GembaOS は宣言に応じて振る舞いを選び、どれを選んだかをその実行の記録に書きます。

相手ができること典型的な接続先GembaOS の振る舞い
バージョン(ETag、If-Match、最終更新日時)Salesforce、kintone、revision 項目を持つ自社 API承認時に読んだバージョンを書き込みに添える。古ければ相手が拒否し、稟議書は差し戻される
条件付き書き込み(「状態がまだ X なら更新」)自社データベースの条件付き UPDATE やストアドプロシージャ承認時の期待値を書き込みに添え、相手が照合する
何もない自社 ERP/CRM の通常の REST 端点、SQL で直接更新する旧システム、支払ファイル(SFTP のバッチ)、HubSpot のように条件付き更新のない SaaS、MES/WMS の保留解除、ディレクトリのパスワードリセット、メール送信GembaOS がそのレコードへの自身経由の書き込みを直列化し、リースの中で読み直し・突合・書き込みを行い、書いた後に読み戻す。読み直しから書き込みまでのミリ秒数を記録に残す

三行目が企業の大半です。GembaOS に同梱の接続設定 12 件のうち 9 件は「何もない」と宣言しています。接続先の仕組みがそうだからです。支払ファイルには冪等キーという概念自体がなく、同じファイルを二度置けば二度支払われるので「再試行不可」と宣言され、タイムアウト後に GembaOS がもう一度置くことはありません。

保証されること、そして閉じずに狭めているところ

何の保護もない接続先に対しても、次の三つは成り立ちます。

閉じずに狭めているのは一か所だけです。GembaOS の外にいる書き手——店舗のレジ係、ERP の画面でレコードを手で直す同僚——が、「読み直し」から「書き込み」までの数十ミリ秒に割り込む場合です。GembaOS はこの窓が閉じているとは言わず、記録します。実行ごとの ExecutionChecked 事象に、どの保護で書き込みを支えたか(相手のバージョン、相手の条件照合、GembaOS 自身のリース)、窓が何ミリ秒だったか、書き込み後の読み戻しが何を示したかが書かれます。読み戻しが一致しない、あるいは読めない場合は黙って通らず、「未確認」の記録として人が見るものになります。

承認者が決裁時に目にするもの

この防御機構は、裏方の見えないブラックボックスではなく、承認者の画面上に明示されます。

GembaOS 稟議画面:返金処理 ORD-20001、金額 68,000 円。「承認後の処理」として元の支払い方法への返金(取り消し不可)、対象、金額、利用枠内判定、有効期限(発行後 30 分間)、実行回数(1 回のみ)、および実行直前再照合項目(承認時レコードとの突合、上限照合、排他ロック、事前宣言)が表示されている
GembaOS 稟議画面:返金処理 ORD-20001、金額 68,000 円。「承認後の処理」として元の支払い方法への返金(取り消し不可)、対象、金額、利用枠内判定、有効期限(発行後 30 分間)、実行回数(1 回のみ)、および実行直前再照合項目(承認時レコードとの突合、上限照合、排他ロック、事前宣言)が表示されている

稟議画面には、タイムラグ対策のパラメータが明確に表示されます。

まとめ

承認までの待機時間は、単なるユーザー体験(UX)の問題ではなく、企業の資産安全に関わるシステム整合性の根本問題です。

人間が判断に関わる限り、時間の経過は避けられません。その経過時間の間に、レコードは書き換わり、同僚は並行して作業し、上限値は変動し、通信はリトライを発生させます。

「Slack で Allow が押されたからそのまま再開する」という既存の素朴なアプローチでは、これらのリスクを何ひとつ防げません。GembaOS の答えは明確です。人間の承認を「その特定時点におけるビジネス判断の是認」として位置づけ、ガバナンスカーネルが書き込み直前の最後の 1 ミリ秒で「その前提が現在の現実世界でも依然として成立しているか」を厳格に再照合し、確かめられなかったところには人のための記録を残すことです。

この記事が答える質問

承認待ちの間や承認後に業務データが書き換わっていた場合、システムはどう対応しますか?

実行は直ちに停止します。GembaOS 実行基盤は業務 API を呼び出す直前に、データベースの最新状態を再取得し、起案時にロックされた前提断言と突合します。重要項目に差分があれば実行を中断してワンタイム許可証を無効化し、差分情報を添えて工單を差し戻します。

起案から数時間放置された後、上長が承認ボタンを押した場合、そのまま実行されますか?

前提が崩れているか許可証が期限切れなら、決して実行されません。承認時に発行されるワンタイム許可証(Clearance Token)には厳格な有効期限(返金なら 30 分等)が設定されている上、実行直前に必ず実データを再取得して前提条件を照合します。離席中に店頭返金等が済んでいれば即座に遮断・差し戻されます。

同じ承認に基づいて処理が二重に実行される恐れはありませんか?

GembaOS が二度送ることはありません。許可証は一度しか消費できず、冪等キーはカーネルが稟議 ID と作業票 ID から生成し、エージェントは指定できません。相手がそのキーを認識する(決済ゲートウェイなど)ならリトライは同じ処理に着地します。認識しない(支払ファイル、自社の端点)なら、タイムアウト後に盲目的な再送はせず、その実行を「未確認」として責任者に回します。

同じレコードに対して複数のエージェントや人間が同時に操作した場合はどうなりますか?

相手の接続先に何ができるかによります。バージョンや条件付き書き込みに対応している(Salesforce、自社データベースの条件付き更新)なら、承認時に読んだバージョンを書き込みに添え、古ければ相手が拒否します。何にも対応していないなら、GembaOS が自身経由のそのレコードへの書き込みを直列化し、リースの中で読み直してから書き、読み直しから書き込みまでのミリ秒数を記録に残します。GembaOS の外の書き手に対して、この窓は閉じるのではなく狭めています。

出典

2026 年 9 月時点で GembaOS は第三者認証を取得していません。本サイトの統制対応表は自己評価であり、監査を受けたものではありません。GembaOS は先行導入パートナーの段階にあります。 先行導入パートナーについて読む。

最終更新: · GembaOS v0.2