Entry 011Incidents7 min readBy Mandare Labs

Moltbook exposed 1.5M agent API keys: what limits damage

Wiz reported on 2 February 2026 that a misconfigured Supabase database at Moltbook exposed about 1.5 million agent API authentication tokens, each a complete login for an agent account. Some agent messages also held plaintext OpenAI keys. What limits that kind of damage is what the platform stores per agent, whether the agent holds the provider key at all, and a cap on that key. None of them fixes a writable database.

Wiz found four kinds of exposure in one database

Wiz's write-up, dated 2 February 2026, describes a security review of Moltbook, a social platform for AI agents, that began by "browsing like normal users". Within minutes the researchers found a Supabase API key in the site's client-side JavaScript. With it, they report, the database answered "exactly as if we were an administrator".

DataWhat Wiz says it heldWhat it allowed
agents tableAn api_key, a claim_token and a verification_code per agent"fully impersonate any agent on the platform"
owners tableEmail addresses and X handles of 17,000+ usersExposure of the email addresses, which Wiz says were meant to stay private
agent_messages table4,060 private conversations between agentsIncluded "plaintext OpenAI API keys shared between agents"
posts and other public tablesSite contentWrite access: Wiz modified an existing post

The timeline in the post: initial contact on 31 January 2026 at 21:48 UTC, the Row Level Security misconfiguration reported at 22:06 UTC, and the final fix at 01:00 UTC on 1 February 2026. Wiz notes that each round of fixes surfaced more exposed tables, from sensitive tables to write access to GraphQL-discovered resources, so the work took several passes.

The post reports counts of about 1.5 million tokens and 35,000 emails, plus 29,631 more addresses in a separate observers table. It also reports that all data accessed during the research and fix verification was deleted.

The key was public by design; the policy behind it was missing

A Supabase publishable key in a web page is normal. Wiz says so itself: "When properly configured with Row Level Security (RLS), the public API key is safe to expose - it acts like a project identifier." The next sentence is the incident: "However, without RLS policies, this key grants full database access to anyone who has it."

Supabase's documentation states the rule in one line: "A table in an exposed schema without RLS is readable and writable by any role with a grant on it." It also gives the expected behaviour once RLS is on: "Once RLS is enabled, no data is accessible through the API when using a publishable key, until you create policies."

The test Wiz ran is therefore one request. Its shape, with placeholders:

curl "https://<project>.supabase.co/rest/v1/<table>?select=*&limit=3" \
  -H "apikey: <publishable key found in the page's JavaScript>"

With RLS working, that request returns an empty array or an authorization error. Wiz describes exactly that expectation before reporting what came back. Writes need their own check. Wiz reports that after the initial fix blocked read access to sensitive tables, "write access to public tables remained open", so read and write policies are separate work.

A stored token turns a table read into a login

The agents table held each agent's api_key, which Wiz describes as a "Full authentication token allowing complete account takeover". The table held the token itself, so reading the row was the same as owning the account. This is the property of a bearer token that the stolen-key entry covers: whoever holds it can use it.

What the verifier keeps per agent decides what a read of that table is worth. RFC 9421 is explicit about the difference between shared secrets and key pairs:

"By their nature, symmetric cryptographic methods require the same key material to be known by both the signer and verifier. This effectively means that a verifier is capable of generating a valid signature, since they have access to the same key material. An attacker that is able to compromise a verifier would be able to then impersonate a signer." (section 7.3.3)

The verifier storesA read of that table gives an attacker
The token itself (Moltbook's api_key, per Wiz)A working login for every row
A shared HMAC secretThe ability to sign as the agent (RFC 9421 section 7.3.3)
A public keyThe key signatures are checked against; no ability to sign

Section 7.3.2 of the same RFC adds that "the use of asymmetric signing algorithms exposes key material less than the use of symmetric signing algorithms". How an agent signs each request is the subject of RFC 9421 for AI agents.

The third row has its own limit. If the table of registered public keys is writable the way Wiz found the posts table to be, an attacker replaces a key and signs as the agent. Wiz demonstrated an edit on a post, not on a key table, so this is a conditional, not a finding. It still means the integrity of that table matters as much as its secrecy.

An agent that holds a provider key can leak it in a message

The agent_messages table is the second lesson. Wiz writes that "some contained third-party API credentials, including plaintext OpenAI API keys shared between agents", and, in its lessons: "Users shared OpenAI API keys and other credentials in direct messages under the assumption of privacy, but a configuration issue made those messages publicly accessible."

A leak in one platform became a credential leak for an unrelated service. OpenAI documents three practices for the key itself. Its production best practices, read on 11 October 2026, say:

An expiry bounds how long a copied key works. A hard limit bounds what it can spend inside that window. OpenAI's cap is monthly; a daily window has to come from a layer in front, as that entry sets out per provider.

The Wiz post does not say whether the exposed OpenAI keys had spend limits or were rotated, so what the leak cost those key owners is not in the record.

Write access and fake agents sit outside any key scheme

Wiz ranks write access above data exposure: "Write Access Introduces Far Greater Risk Than Data Exposure Alone". Its reasoning is "content manipulation, narrative control, and prompt injection that can propagate downstream to other AI agents". A signed request, a short token lifetime and a spend cap all concern who is calling and how much they spend. None of them says whether the content an agent reads is the content someone wrote.

The ratio in the post is a separate point. Wiz reports 1.5 million registered agents against about 17,000 human owners, an 88:1 ratio, and writes that "Anyone could register millions of agents with a simple loop and no rate limiting". It also says "The platform had no mechanism to verify whether an 'agent' was actually AI or just a human with a script."

A key proves possession of a key. It does not prove an LLM is behind it. A platform that wants to count agents has to decide what it is counting. Wiz says the number "can be easily inflated without guardrails like rate limits or identity verification".

Where Mandare fits, and what it does not do

Mandare is a local door in front of an agent's LLM calls, not a platform and not a database. As of v0.1.0 (npm view @mandarelabs/cli version on 11 October 2026), checked against commit 327442e of the public repository, it would not have changed Moltbook's RLS misconfiguration, and it does not protect a third party's tables. What it changes is how a reader's own agents hold credentials:

Limits next to those claims:

Questions

What did the Moltbook database exposure include?

Wiz's write-up of 2 February 2026 lists about 1.5 million API authentication tokens, 35,000 email addresses and private messages between agents, with read and write access. Some messages held plaintext OpenAI API keys. Wiz reported the issue on 31 January 2026 and the final fix landed at 01:00 UTC on 1 February 2026.

Is a Supabase publishable key safe to put in client-side code?

Yes, when Row Level Security is enabled on every table in an exposed schema and policies grant just what each role should reach. Supabase's documentation says "A table in an exposed schema without RLS is readable and writable by any role with a grant on it." Without RLS the key in the page is a full-access credential, which is the situation Wiz describes.

Does storing a public key instead of an API key stop impersonation after a database leak?

It removes the stolen credential: a public key cannot sign. RFC 9421 section 7.3.3 says that with symmetric methods "a verifier is capable of generating a valid signature". It does not protect the key table from writes, because an attacker who can replace a registered key can register their own.

Would a spend limit have helped with the leaked OpenAI keys?

A hard spend limit caps what a thief can spend on a key, not what they can read. OpenAI documents that hard spend limits "stop affected API traffic when tracked spend reaches the limit". Wiz does not say whether the exposed keys had limits or were rotated.

Sources

  1. Hacking Moltbook: AI Social Network Reveals 1.5M API Keys · Wiz · 2026-02-02
  2. Row Level Security · Supabase
  3. RFC 9421: HTTP Message Signatures · IETF / RFC Editor · 2024-02-01
  4. Production best practices (OpenAI API documentation) · OpenAI

Run it yourself: 3 commands, no API keys.

github.com/mandarelabs/mandare →
← All journal entries