Incident
Moltbook is a social site where AI agents post, comment and vote, and it drew wide attention in the AI community over a period of days. The platform's founder had said publicly that the site was built without hand-written code: "I didn't write a single line of code for @moltbook. I just had a vision for the technical architecture, and AI made it a reality."
The security firm Wiz reviewed the site by browsing it as an ordinary visitor. Within minutes it found a database key sitting inside the page files the site sends to every browser. Used against the database, that key was answered as though it belonged to an administrator, returning the sign-in keys of registered agents. Wiz reported that 1.5 million such keys were exposed.
Working from there, the researchers mapped the tables and counted around 4.75 million records. One table held personal details for 17,000+ of the affected account owners. Another held 29,631 email addresses gathered for an upcoming product, making 46,631+ addresses in all; the report's own opening summary gives a lower email total that does not match its itemised tables. A further table held 4,060 private conversations, some carrying keys to other paid services. The site publicly claimed 1.5 million registered agents against 17,000 human owners, a ratio of 88:1.
Wiz contacted the maintainer that evening by direct message. An initial repair closed the tables holding agent keys, owner details and site administrators; a further repair covered messages, notifications, votes and follows. The researchers then found that changing content was still open and edited a post as a test, and another repair blocked changes. More exposed tables surfaced, and a final repair secured all of them within hours of the initial message. The team deleted the test content a few hours later and thanked the researchers.
Wiz said the data it accessed was deleted. Its report raises the question of whether posts, votes and karma scores were altered during the exposure window. An independent security researcher separately found the same database setting, and that finding was covered by a news outlet.
Primary source — S1: https://www.wiz.io/blog/exposed-moltbook-database-reveals-millions-of-api-keysSnapshot
Cause of loss
- The database's per-record permission rules were never switched on, so the key carried in every visitor's browser was answered as if it belonged to an administrator. This database checks, row by row, whether the requester is allowed to see or change that row, but only once those rules are turned on; until then it answers every request in full. With the rules off, a key meant to identify the project became a key that read and wrote sign-in keys, personal details and private messages.Technical name: row level security
- The key that unlocked the database was shipped inside the page files the site sends to every visitor, where anyone reading the page could copy it. This kind of key is designed to be visible, and publishing it is normal practice; its worth depends entirely on the permission rules sitting behind it. With those rules off, putting the key in the page put the whole database within reach of anyone who looked.Technical name: client-side credential exposure
- Nothing required a visitor to prove who they were before changing the site's public content, so any stranger could rewrite any post. Reading and writing are separate permissions, and closing the sensitive tables to reading left the writing path open. Content changed that way is then read by the agents on the platform, so an edit made by an outsider travels onward as if the platform had published it.Technical name: unauthenticated access
Finding
Two things look identical from the outside: a public key that is safe to publish, and a public key that hands over the entire database. What separates them is a permission layer that stays off until someone deliberately turns it on. Because the difference is invisible from the credential, no one finds out which one they shipped until an outsider does.
Verification
What only you can answer
- When you were told the key in your app's pages is safe to publish, were you told that its safety depends on a separate switch inside the database, and did you ever ask whether that switch was on for every table?
- If a stranger could read one table of yours today, which one would hurt most, and does your private-message or support area hold keys and passwords to other services you pay for?
- When someone reports a fix as done, what does done mean to you: that outsiders can no longer read your data, that they can no longer change it, or both, and would you accept that answer without it being written down?
What your AI can check
Report only; do not change any code or configuration. Answer each question with file or console references for every claim.
- Enumerate every table and view in the project's database and report, for each one, whether row level security is enabled and which policies apply to the anonymous role for select, insert, update and delete. Flag any table with RLS disabled or with a permissive policy that has no condition on the requester, and cite file or console references.
- Report whether the schema is reachable through the REST and GraphQL endpoints by an anonymous caller, including whether error messages or introspection disclose table and column names beyond those intended to be public, and cite file or console references.
- Search the built front-end bundles and any deployed static assets for database URLs, API keys and other configuration values that reach the browser. For each key found, report its type, which project it points to, and what an outsider holding it could do given the current policies. Cite file or console references.
- Report whether write operations from an anonymous caller are rejected on every table, distinguishing read policies from insert, update and delete policies. Also report whether the project has an automated test that asserts anonymous writes are refused, and whether that test runs on every change; cite file or console references.
Prevention
Get a table-by-table yes before launch, in writing. Ask whoever set up your database to send you a list of every table with a yes or no beside each: does this table refuse strangers? Keep that list, and ask for it again every time a new table is added, because a new table starts out answering everyone.
Treat every key in your app's pages as already published. Assume a stranger has it, then ask one question of your database supplier or your developer, in writing: with this key and nothing else, what can someone read and what can someone change? If the answer is anything more than the public pages themselves, that is the finding, not the key.
Ask about changing data separately from reading it. When a repair is reported as complete, require two confirmations: outsiders can no longer read, and outsiders can no longer edit, add or delete. Until you have both, assume anything you display publicly can be rewritten by someone else, and do not put keys or passwords for other services into messages, notes or support threads stored in that database.
A key that is safe to publish and a key that hands over your database look exactly the same from the outside; only the setting behind it tells you which one you shipped.