Appwrite runtime vulnerability (Nov 1): what to rotate
Only if Appwrite emailed you. Its Nov 4 incident report says that on Nov 1, from 03:53 to 14:46 UTC, a credential taken from a Frankfurt routing service "could have been used to read the environment variables of Functions and Sites running on our Frankfurt compute." Appwrite "found no evidence that the attacker read any variables using that credential," but "as a precaution" it is notifying every customer whose Functions or Sites could have been exposed — the owners of 1,022 projects.
If you got that email, treat every secret-named variable that meets Appwrite's three conditions as exposed, and rotate it at the service that issued it. Appwrite can't rotate those for you. If you weren't contacted, Appwrite says none of your projects met the conditions.
Who is on the 1,022-project list
Appwrite notifies a project only when all three are true:
It had a function or site running on Appwrite's Frankfurt compute between 03:53 and 14:46 UTC on November 1st. "This compute also serves sites for projects in our other regions, so some of those projects are included."
That function or site had an environment variable that was set before 14:46 that day.
The variable's name "marks it as a secret, such as a key, token, password, or database connection string." Appwrite left out "variables that are public by design, such as publishable keys and public client IDs."
What Appwrite has said (Nov 1–4)
Nov 1, 03:53 UTC: from a project of their own, the attacker exploited a Sites and Functions runtime vulnerability and got the Frankfurt service's credentials. One of those was "an access token that could read the configuration of every function and site on that Frankfurt compute, environment variables included."
Nov 1, 14:46 UTC: a routine release replaced the affected service; the access token stopped working. Window: about 11 hours.
Nov 2: automated monitoring detected the attack; Appwrite blocked the attacker's accounts and projects, shipped the fix, and replaced every exposed credential. "The old values are now refused everywhere."
Nov 4: Appwrite started notifying affected customers. The report is titled for November 1st and published Nov 4.
Appwrite says the attacker's activity with other credentials "was aimed at a single customer," and that for the Frankfurt access token its infrastructure provider's audit log for the window is incomplete, so it "can't fully rule out" a read. The FAQ: "Did the attacker read my environment variables? We found no evidence… We can't fully rule it out."
Rotate what Appwrite lists
These four come from Appwrite's "What you should do." Do them only if you were emailed. For any secret issued by another service: create the replacement there, revoke the old one, then update Appwrite and redeploy.
Create new values at each issuer, then revoke the old ones. "Create new values at the service that issued each secret (payment provider, email provider, AI provider, database, and so on), then revoke the old ones." Our note: pull each provider's usage for Nov 1 onward before you revoke, while you still know which key was which. If a payment key is on the list, a Stripe secret key can create charges, issue refunds and read customer data; roll it as in rotating a leaked Stripe key without breaking webhooks, and afterwards a read-only scan such as Stripe Leak Check flags card-testing bursts, fraud warnings you can still refund and disabled webhook endpoints, using only a read-only restricted key.
Appwrite API keys. "For Appwrite API keys, create a new API key with only the scopes the function needs, update the variable, redeploy, then delete the old key." Appwrite's API-key docs: open API Keys in the project sidebar, Create API key, pick only the scopes you need, then "create a new key, update your app credentials and, once ready, delete your old key."
Update the variable on each affected Function or Site and redeploy. Appwrite: "Update the variable in each affected function or site and redeploy it, so running copies pick up the new value." Its Functions and Sites docs both say "Variable changes only take effect on the next deployment." Project variables are shared across every function and site; function- or site-scoped variables override matching project keys. Secret-marked variables hide their value after creation — to replace one, delete it and create it again with the same key.
Check provider logs since 03:53 UTC on November 1st. "Check each service's own logs for activity you don't recognise since 03:53 UTC on November 1st."
Want us to run it for you? The Ship Check Audit lists every key that ever left your server and confirms each old value now gets a 401 or 403: $149, within 48 hours.
Self-hosting Appwrite
"This incident happened on Appwrite Cloud. If you self-host Appwrite, upgrade to the 2.7.1 patch release, which brings the same root-cause fix to self-hosted installs. Follow the updates and migrations guide to upgrade." Cloud customers on the notify list still rotate their own secrets as above; the patch is the platform fix, not a substitute for rotating customer secrets.
Then check that the old values are dead
Test each old third-party value directly. 401 means revoked:
After you delete an old Appwrite API key in the Console, any Server SDK call that still uses it should fail authentication. Confirm with a trivial call against your project endpoint using only the old key.
Redeploy each Function and Site you changed, then run one execution or SSR request that needs the new value and confirm it succeeds.
Not on Wiz's list
Appwrite isn't one of the twelve AI developer platforms in Wiz's "Black October" post (latest edit Nov 3, 15:40 UTC), but the exposed surface is the same class of secret: environment variables on a developer platform. If you also used one of those twelve, see Black October: every AI dev platform breach in one list. A key you rotated after one of them and then stored on Appwrite needs rotating again if Appwrite emailed you.
Ship Check Kit · $29
Rather not run it by hand?
The Ship Check Kit has your coding agent find every key that ever left the server (SC-SEC-01 for git history, SC-SEC-02 for the browser bundle) and then confirm each old value is actually revoked, not just replaced (SC-SEC-03, which fails while an old value still gets anything but a 401 or 403). Three of 44 launch checks, each with the evidence and the fix.