English version below

技術レポート:AI の「コード実行」から、本番の鍵のほぼすべてが抜かれるまで

株式会社イネブラ(teai の運営会社)/掲載 2026年11月9日/時刻は日本時間

お客様へ(先にお読みください)

このレポートは技術者向けです。お客様へのお願いと、読まれたおそれがある情報のくわしい説明は、お知らせにまとめています。要点は次のとおりです。

読まれたおそれがある情報

実際にどこまで読まれたかは、調べています。

お願いしたいこと

  1. メールアドレスとパスワードでログインしている方は、teai.io をご自分で開き、パスワードを再設定してください。同じパスワードをほかで使っていれば、そちらも変えてください。
  2. teai に他社の API キーを登録したことがある方は、各社で作り直してください(11月9日の集計では、お客様が登録したキーは0件でした)。
  3. Sente・te や teai の API をお使いの方は、teai.io/keys で API キーを作り直し、古いキーを削除してください。11月9日17時10分より前からあるキーは、11月21日に当社がすべて使えなくします。
  4. 当社を名乗るメールのリンクは開かないでください。

現時点で確認できていること

問い合わせ先:teai.io/contact

要約

1. 構成(当時)

code_execute の作り(当時)

2. 攻撃の流れ(確認できた事実)

アカウントは記号で示します(A〜F)。

日時(JST)誰が起きたこと
9/8〜A(実在しないドメインのメールで登録した4件)code_execute でサーバーの中を調べた
9/21B本体の環境変数を取得。管理用の鍵で自分に20万クレジットを付与。/data に目印のファイルを置いた
9/22 00:24(外部)漏れたクラウドの鍵で、バックアップの保管庫(S3)に目印のファイルを書き込んだ
9/22〜11/7(外部の約10の IP)漏れたクラウドの鍵で、権限を一斉に確かめた。S3 の1バケットへの書き込みは成功した。読み出しも権限上はできたが、記録がないため持ち出されたものとして扱う。ほかの操作は拒否された
9/25—AI 利用(OpenRouter)の鍵の値を取得
9/27 16:33C代表のメールアドレスでパスワードを5回試した(すべて失敗)
9/27 16:41C漏れたデータベースの鍵で、代表アカウントの偽のログイン情報(期限 2027-12-31)を直接書き込んだ。代表アカウントで API キーを作り、50万クレジットを付与した
9/27〜C(代表として)環境変数の全文を取得。データ暗号の鍵、パスワード照合の鍵、管理用の鍵が含まれる。当社がクラウド(Cloudflare)に保存していたデータ(KV)も読み出された(お客様の情報が含まれていたかは確認中)
9/28—サーバー上で SSH サーバーと端末共有ツール(tmate)を起動された。外から実際に接続できたかは不明。同じ日に、設定だけを変えたリリース(v1407)がある(自社の操作かを照合中)
10/12〜11/9 16:48(外部から直接)自社6ドメインを差出人に、詐欺メール 75,964 通。使われた鍵は、teai の鍵だけとは限らない(teai の鍵を消したあとも、同じメール送信のアカウントにあった、ほかの鍵で送られていた)
11/3・11/7D・E同じ手口で環境変数を取得
11/9—当社が、AI 利用残高の不具合の調査中に、データベースの記録から発見
11/9F隔離のあと、同じ系統の使い捨てアドレスで2回再登録した(13:32・15:20。いずれも利用なし。隔離済み)。同じ日、攻撃者は同じカードで、別の決済画面を使ったとみられる購入を再び試みた(決済会社の不正検知で拒否)

攻撃者がデータベースに直接書き込んだもの:偽のログイン情報1件と、作業用の表1つ(発見時は空)です(API キーの作成と利用枠の付与は、アプリの機能を通じた操作です)。見た範囲では、お客様のデータが書き換えられた形跡はありません。全件の照合はまだ終わっていません。

お金の動き

3. なぜ防げなかったか

  1. 隔離の単位を誤った:子プロセスの環境変数を消すことを、隔離だと考えていました。同じマシン・同じユーザーである限り、/proc から本体が見えます。
  2. 生の出力を利用者に見せた:AI の判断とは別に、道具の出力がそのまま画面へ流れていました。
  3. AI を防御に数えた:AI はだまされます。防御は、権限・ネットワーク・ファイルシステムの側に置くべきでした。
  4. 鍵を1か所に集め、強い鍵を共用した
    • 全部の鍵が、本体の環境変数に平文で並んでいました。
    • メール送信は全権限の鍵を複数のサービスで、決済の鍵は当社のアプリ25と Worker 5つで共用していました(配布用の一覧には、そのうちアプリ14しか載っていませんでした)。
  5. 管理者の権限を、チャットにも持たせていた:利用者のチャットでは、道具の出力は画面に先頭500文字しか出ません。攻撃者が代表アカウントを乗っ取ったのは、代表のチャットでは管理者だけが使える道具も使え、環境変数の全文を受け取れたためとみられます。人の管理画面の権限と、AI に持たせる権限を分けていませんでした。
  6. ログイン情報を平文で保存していた:データベースの鍵を持つ者が、任意のログイン情報を書き込めました。乗っ取りの直接の原因です。
  7. 古いパスワードを残していた:8月に遅いハッシュ(argon2)へ切り替えていましたが、移行は「次にログインしたとき」だけでした。パスワードを持つ69人のうち、ログインしていない47人のパスワードは、秘密の鍵を加えた速いハッシュ(旧方式)のまま残り、その鍵が漏れました。
  8. 登録と付与の悪用に気づけなかった:実在しないドメインや使い捨てのアドレスで登録できました。20万・50万クレジットの付与にも警報がありませんでした。
  9. 外を見ていなかった:次の異常に見張りがなく、約1か月気づけませんでした。
    • 詐欺メールの送信数と苦情率
    • AI の利用料
    • クラウドの権限エラーの急増
    • 外向きの通信(tmate は外へつなぐ道具です)

4. ご自身の環境で確かめてほしいこと

AI に道具を持たせているサービスを作っている方へ。検証用の環境で確かめてください(本番では試さないでください)。

隔離の手段としては、microVM(Firecracker など)、gVisor、少なくともプロセス名前空間の分離と hidepid=2、そして別ユーザーでの実行があります。

5. 対応と再発防止

対策状態
code_execute ほか、サーバー上でコマンドやファイル操作をする道具を、既定で無効にする実装・本番反映済み(11/9)
道具の出力から秘密を自動で消す(値そのもの・16進数・base64・鍵らしい形)実装・本番反映済み(11/9)
サーバーの状態や設定を返す道具を AI から外す実装・本番反映済み(11/9)
関わった13アカウントの隔離と、API キー・ログインの失効(表の A〜F のほか、登録元や使い方から同じ系統と判断したものを含む)済(11/9)
代表アカウントの偽のログイン情報と、攻撃者が作ったキーの削除済(11/9)
データベースの鍵の入れ替え(旧鍵はすべて無効)済(11/9 17:10)
データ暗号の鍵の入れ替えと再暗号化済(11/9)
管理用の鍵・AWS の鍵の入れ替え済(11/9)
メール送信の鍵:全削除し、アプリごとの送信専用の鍵へ済(11/9 17:36)。以後の詐欺メールがないことを 11/9 17:37 と、22時台(送信の一覧の直近分)に確認
ログイン情報のハッシュ保存と、すべてのウェブのログイン状態の解除実装・本番反映済み。解除も実行し、0件を確認(11/9)
決済の鍵済(11/9。全サービスで新しい鍵が使えることを確認)
Cloudflare・RunPod・Google・LINE・AI 各社の鍵一部済(11/9 に Cloudflare のグローバル鍵と、OpenRouter・Google の AI の鍵を入れ替え、古い鍵を削除)。ほかは作業中
本番マシンの作り直し、または置かれた仕組みの残存確認確認中
旧方式の47人に再設定をお願いし、旧方式ではログインできないようにする(パスワードを持つ69人全員にも念のためお願いする。再設定すると argon2 に移る)再設定の仕組みは本番反映済み。旧方式でのログインを止める変更:済(11/9 の本番反映。本番で 403 を確認)。個別のご案内は、これから送ります
漏れた GitHub トークン11/9 の時点ですでに無効(いつ無効になったかは確認中)。攻撃の期間中に悪用された形跡は、見た範囲では見つかっていない
AI 利用料の使途不明分(約 $4,925)の調査調査中。11/14に報告
代表アカウントの連携トークン10件の再発行作業中
9/28 の設定だけのリリース(v1407)が当社の操作かの照合照合中。11/14に報告
外部サービス側の異常の見張りを強める進行中。11/14に報告。目安は2026年12月中
登録と利用枠の付与の監視を強める進行中。11/14に報告。目安は2026年12月中
バックアップの保管の守りを強める進行中
メールを送る全ドメインに DMARC を設定し、拒否する設定へ段階的に移す(主な7ドメインは監視の設定まで済み)進行中。目安は2026年12月中
人の管理画面の権限と、AI に持たせる権限を、仕組みとして分ける(上の道具の除外に続く見直し)進行中(AI から道具を外す部分は済)
コード実行の再開鍵のない別マシンで動かす作りに改めるまで再開しない。再開するときは事前に告知

当社の作業ミス:11/9 16:49〜17:10、データベースの鍵の入れ替えで、道具の「成功」をそのまま信じ、無効な値を本番に入れて、サービスを21分止めました。新しい鍵で実際に接続できることを確かめてから入れる手順に改めました。

同じ日の 19:00〜19:31 ごろには、決済の鍵の整理で、まだ使われていた鍵まで無効にし、当社のアプリ25と Worker 5つで決済を止めました。19:03 に見張りが検知し、19:24 と 19:31 に新しい鍵で戻しました。この時間帯に完了した決済は0件で、二重の請求や、支払い後の反映漏れはありませんでした(無効な鍵での呼び出しは決済会社に届かないため、失敗した件数は数えられません)。鍵を無効にする前に、サーバーについては同じ鍵を使う所を設定から自動で洗い出し、サーバー以外の配布先は一覧で管理したうえで、すべてで新しい鍵が使えることを確かめてから無効にする手順に改めました(次回の入れ替えから使います。11/14 までに、本番を変えない形で試します)。

6. 報告と通報

7. 守(Mamori)として

私たちは「守(Mamori)」というセキュリティの見張り役を作っています。それでも防げませんでした。Mamori が見ていたのは、端末やサーバーの設定と、世の中で知られている攻撃の情報です。アプリの作り、鍵の持ち方、外部サービスの異常は、見ていませんでした。

ここまで細かく公開するのは、同じ作りのサービスを持つ方に、同じことを起こしてほしくないからです。防御に役立つ痕跡(悪用された鍵を試した接続元など)は、公的な窓口(CERT・警察)と非公開で共有します。

濱田優貴(株式会社イネブラ 代表取締役)

Technical Report: From an AI "Code Execution" Tool to the Theft of Nearly All of Our Production Secrets

Enabler Inc. (operator of teai) / Published November 9, 2026 / All times are JST (UTC+9)

To Our Customers (Please Read First)

This report is written for engineers. What we ask of customers, and a detailed explanation of the information that may have been read, are in our notice. The key points are below.

Information that may have been read

We are investigating how much was actually read.

What we ask you to do

  1. If you log in with an email address and password, open teai.io yourself and reset your password. If you use the same password anywhere else, change it there too.
  2. If you have ever registered another company's API key with teai, regenerate it with that provider. (As of our count on November 9, customers had registered 0 such keys.)
  3. If you use Sente, te, or the teai API, create a new API key at teai.io/keys and delete your old keys. On November 21, we will disable all keys that existed before 17:10 on November 9.
  4. Do not open links in emails that claim to be from us.

What we have confirmed so far

Inquiries: teai.io/contact

Summary

1. Architecture (at the Time)

How code_execute was built (at the time)

2. How the Attack Unfolded (Confirmed Facts)

Accounts are identified by letters (A–F).

Date/time (JST)WhoWhat happened
9/8–A (4 accounts registered with emails at nonexistent domains)Explored the inside of the server using code_execute
9/21BObtained the main process's environment variables. Used the admin key to grant itself 200,000 credits. Placed a marker file in /data
9/22 00:24(External)Used the leaked cloud key to write a marker file into the backup storage (S3)
9/22–11/7(About 10 external IPs)Used the leaked cloud key to probe permissions across the board. Writing to one S3 bucket succeeded. Reading was also possible under the permissions, but because there are no logs, we treat the data as taken. Other operations were denied
9/25—The value of the AI usage (OpenRouter) key was obtained
9/27 16:33CTried 5 passwords against our CEO's email address (all failed)
9/27 16:41CUsed the leaked database key to write a forged login session for our CEO's account directly into the database (expiring 2027-12-31). Created an API key as our CEO's account and granted 500,000 credits
9/27–C (as our CEO)Obtained the full contents of the environment variables, including the data encryption key, the password verification key, and the admin key. Data we stored in the cloud (Cloudflare KV) was also read (we are checking whether it included customer information)
9/28—An SSH server and a terminal-sharing tool (tmate) were started on the server. It is unknown whether anyone actually connected from outside. On the same day there was a configuration-only release (v1407) (we are checking whether this was our own operation)
10/12–11/9 16:48(Directly from outside)75,964 phishing emails sent with six of our domains as the sender. The keys used were not necessarily only teai's keys (sending continued with other keys in the same email-sending account after teai's keys were deleted)
11/3, 11/7D, EObtained the environment variables using the same technique
11/9—We discovered it from database records while investigating a problem with AI usage balances
11/9FAfter the accounts were isolated, re-registered twice using disposable addresses from the same family (13:32 and 15:20; neither was used; both isolated). On the same day, the attacker again attempted a purchase with the same card, apparently via a different checkout page (rejected by the payment processor's fraud detection)

What the attacker wrote directly to the database: one forged login session and one working table (empty when discovered). (Creating API keys and granting credits were done through the app's own features.) Within the scope we have examined, we have found no sign that customer data was altered. We have not yet finished checking all records.

Money

3. Why We Failed to Prevent It

  1. We drew the isolation boundary in the wrong place: we thought clearing the child process's environment variables was isolation. As long as it is the same machine and the same user, the main process is visible from /proc.
  2. We showed raw output to users: separately from the AI's judgment, tool output flowed straight to the screen.
  3. We counted the AI as a defense: AI can be fooled. Defenses should have been placed in permissions, the network, and the file system.
  4. We kept all secrets in one place and shared powerful keys
    • All secrets sat in plaintext in the main process's environment variables.
    • A full-permission email-sending key was shared across multiple services, and the payment key was shared across 25 of our apps and 5 Workers (our distribution list covered only 14 of those apps).
  5. Admin privileges were also available in chat: in a regular user's chat, only the first 500 characters of tool output appear on screen. We believe the attacker took over our CEO's account because, in our CEO's chat, admin-only tools were also available and the full contents of the environment variables could be received. We had not separated the permissions of the human admin console from the permissions given to the AI.
  6. Login sessions were stored in plaintext: anyone with the database key could write an arbitrary login session. This was the direct cause of the account takeover.
  7. Old passwords were left in place: in August we switched to a slow hash (argon2), but migration happened only "at the next login." Of the 69 people with passwords, the passwords of the 47 who had not logged in remained in a fast hash with a secret key added (the old scheme), and that key leaked.
  8. We did not notice abuse of sign-up and credit grants: accounts could be registered with nonexistent domains or disposable addresses. There were no alerts for grants of 200,000 or 500,000 credits.
  9. We were not watching the outside: there was no monitoring for the following anomalies, and we did not notice for about a month.
    • Phishing email sending volume and complaint rate
    • AI usage fees
    • Spikes in cloud permission errors
    • Outbound network traffic (tmate is a tool that connects outward)

4. What We Ask You to Check in Your Own Environment

For those building services that give tools to an AI. Please check these in a test environment (do not try them in production).

Isolation options include microVMs (such as Firecracker), gVisor, and at a minimum process namespace isolation with hidepid=2, plus running as a separate user.

5. Response and Prevention

MeasureStatus
Disable by default code_execute and other tools that run commands or perform file operations on the serverImplemented and deployed to production (11/9)
Automatically remove secrets from tool output (the values themselves, hex, base64, and key-like patterns)Implemented and deployed to production (11/9)
Remove tools that return server state or configuration from the AIImplemented and deployed to production (11/9)
Isolate the 13 involved accounts and revoke their API keys and logins (A–F in the table, plus accounts we judged to be from the same family based on registration source and usage patterns)Done (11/9)
Delete the forged login session for our CEO's account and the keys created by the attackerDone (11/9)
Rotate the database key (all old keys disabled)Done (11/9 17:10)
Rotate the data encryption key and re-encryptDone (11/9)
Rotate the admin key and AWS keysDone (11/9)
Email-sending keys: delete all and move to send-only keys per appDone (11/9 17:36). Confirmed no further phishing emails at 17:37 on 11/9 and again after 22:00 (the most recent sends in the sending log)
Store login sessions as hashes and end all web login sessionsImplemented and deployed to production. Sessions also ended, with 0 remaining confirmed (11/9)
Payment keysDone (11/9; confirmed that the new keys work across all services)
Keys for Cloudflare, RunPod, Google, LINE, and AI providersPartly done (on 11/9 we replaced the Cloudflare global key and the OpenRouter and Google AI keys, and deleted the old keys). The rest are in progress
Rebuild production machines, or confirm no planted mechanisms remainBeing checked
Ask the 47 people on the old scheme to reset their passwords and block login with the old scheme (also ask all 69 people with passwords, as a precaution; resetting moves them to argon2)Reset mechanism deployed to production. Blocking login with the old scheme: Done (deployed on 11/9; confirmed 403 in production). Individual notices: to be sent
Leaked GitHub tokenAlready invalid as of 11/9 (when it became invalid is still being checked). Within the scope we have examined, no sign of misuse during the attack period
Investigate the unaccounted-for AI usage fees (about $4,925)Under investigation. Will report on 11/14
Reissue 10 integration tokens for our CEO's accountIn progress
Check whether the configuration-only release on 9/28 (v1407) was our own operationBeing checked. Will report on 11/14
Strengthen monitoring for anomalies on the side of external servicesIn progress. Will report on 11/14. Target: within December 2026
Strengthen monitoring of sign-ups and credit grantsIn progress. Will report on 11/14. Target: within December 2026
Strengthen protection of backup storageIn progress
Set up DMARC on all domains that send email and move in stages to a reject policy (monitoring configured for the 7 main domains)In progress. Target: within December 2026
Structurally separate the permissions of the human admin console from the permissions given to the AI (a review following the tool removal above)In progress (removing the tools from the AI is done)
Resuming code executionWill not resume until it is redesigned to run on a separate machine with no secrets. We will announce in advance before resuming

Our own operational mistakes: from 11/9 16:49 to 17:10, while rotating the database key, we trusted a tool's "success" message at face value, put an invalid value into production, and took the service down for 21 minutes. We changed our procedure to confirm that we can actually connect with the new key before putting it in place.

On the same day, from about 19:00 to 19:31, while cleaning up payment keys, we also disabled a key that was still in use, which stopped payments on 25 of our apps and 5 Workers. Our monitoring detected this at 19:03, and we restored service with new keys at 19:24 and 19:31. Zero payments were completed during this window, and there were no double charges or payments that failed to be applied after being made. (Calls made with an invalid key do not reach the payment processor, so we cannot count how many failed.) We changed our procedure so that, before disabling a key, we now automatically find every server that uses it from our configuration, track non-server destinations in a list, and disable the old key only after confirming the new key works everywhere (this applies from the next rotation; we will test it without touching production by 11/14).

6. Reporting and Notifications

7. As the Makers of Mamori

We build a security watchdog called "Mamori" (守). Even so, we could not prevent this. What Mamori watched was the configuration of devices and servers, and publicly known attack information. It did not watch how applications are built, how secrets are held, or anomalies in external services.

We are publishing this level of detail because we do not want the same thing to happen to others running services built the same way. Traces useful for defense (such as the source addresses that tried the misused keys) will be shared privately with public authorities (CERTs and the police).

Yuki Hamada (CEO, Enabler Inc.)

Related: Notice (what to do) / Technical report / Phishing emails / Contact: teai.io/contact


関連:お知らせ(お願い) / 代表のまとめ / 技術レポート / 停止のお詫び / 対応の記録 / 詐欺メールについて/お問い合わせ:teai.io/contact