In short
- Replit runs the platform: isolated environments, encrypted Secrets, DDoS filtering at the edge, SOC 2 Type II. Its own shared responsibility model makes access control and pen testing of your app your job.
- Since the July 2025 database deletion, every app has separate development and production databases. Agent reads production only through a read replica, and production keeps 7 days of point-in-time recovery by default.
- The browser never talks to Replit's database. Your data leaves through your own Express routes, so the leaks sit there: no sign-in check, or a sign-in check with no owner check.
- Security Center Level 1 is free and checks dependencies only. Level 3 adds a black-box test of the Preview, while your published app runs with its own secrets, database and users.
- Test the published URL after every republish: signed out, as a second account, and for secret keys in the JavaScript.
On this page
- Is Replit safe? The short answer
- What Replit is responsible for, and what you are
- The stack Replit Agent builds, and where it leaks
- What Replit's own security tools catch
- Replit security concerns, with concrete examples
- How to check your Replit app
- Fixes, with prompts for Agent
- Replit deployment security: the traps after the first fix
- Test the published app after every deploy
- Replit app security checklist
- Questions
- Sources
Is Replit safe? The short answer
Yes for the platform, with a condition for your app. Replit isolates development environments from each other, encrypts secrets with AES-256, encrypts traffic and stored data, filters DDoS at the edge and holds a SOC 2 Type II attestation. It also blocks malicious packages at install time and runs a security scan before each publish. None of that decides who can read the data inside the app Agent wrote for you.
Replit says so itself. Its shared responsibility model lists user management, access control, the data your app handles and penetration testing of your app as yours. Replit answers for the Agent, the platform and the infrastructure. You own the code Agent generates, including how it signs people in and what it lets each of them read.
The worry behind many of these searches dates from July 2025, when Replit Agent deleted the production database of SaaStr founder Jason Lemkin during a code freeze. Replit's CEO called it unacceptable and the company moved apps to separate development and production databases. Today Agent can change the development database but only reads production through a read-only replica, and production keeps 7 days of point-in-time recovery by default. That incident was about the agent. The risks below are about the app.
What Replit is responsible for, and what you are
| Area | Who owns it | What it means for your app |
|---|---|---|
| Platform, runtime, edge and encryption | Replit | Sandboxes, patches, DDoS and WAF, TLS. After a critical Node.js flaw in January 2026, published apps got the patched runtime on their next republish. |
| Secrets storage | Replit | Values encrypted at rest and never logged in plain text. Putting every key in Secrets, not in code, is your part. |
| Dependency vulnerabilities | Replit detects, you fix | New CVEs in your packages appear in the Security pane. The fix reaches production when you republish. |
| Backups of code and Replit databases | Replit | Production gets point-in-time recovery; scheduled daily backups are optional. |
| Who can open the published app | Replit gives the switch, you choose | Public, password protected, workspace only or invite only. |
| User management and access control | You | Who can sign in, and which records each user can read or change. |
| Code review and pen testing of your app | You | Replit's scans help. The responsibility stays with you. |
| Privacy and compliance of your app | You | GDPR, HIPAA, PCI DSS: they apply to what you built. |
The stack Replit Agent builds, and where it leaks
Web apps are Replit's default output, and each one is full stack. Replit's docs describe the pieces: Clerk's React components in the frontend, Clerk's Express middleware on the API routes, and drizzle-kit migrating a PostgreSQL 16 database. In practice: a React app, an Express server, and Postgres through the Drizzle ORM.
That shape matters. On Supabase or Firebase, the browser queries the database and database rules protect the data. In a Replit app, the browser never reaches the database: every record passes through a route in your own server. So the leaks in a Replit app sit in that server code, and in what the build ships to the browser.
| Layer | What Replit sets up | Where leaks happen |
|---|---|---|
| Frontend | React, compiled into the JavaScript every visitor downloads | Keys bundled into that JavaScript (if the frontend builds with Vite, every VITE_ variable it reads ships there), and admin screens hidden only by a React condition |
| API | Express routes, also used by a mobile app in the same project | Routes with no sign-in check, or a sign-in check but no owner check |
| Database | PostgreSQL 16 through Drizzle: one database for development, one created for production when you publish | Not reachable from the browser. It leaks through the API, or through a leaked production connection string |
| Auth | Clerk by default on Starter, Core and Pro; Replit Auth by default on Enterprise | Sign-in is handled for you. Authorization, who owns which record, is your code |
| Files | App Storage: Google Cloud Storage buckets that are always private, read by your server | The route that serves a file decides who gets it |
| Secrets | The Secrets tool, read as environment variables, with separate production secrets | Safe on the server. Exposed once copied into frontend code, a project file or the Agent chat |
| AI | Replit AI Integrations (paid plans), billed to your Replit credits at public API prices | An AI route with no sign-in and no limit lets strangers spend your credits |
What Replit's own security tools catch
Replit's own security tools are worth using. Here is what each one covers:
| Tool | What it checks | Cost and default |
|---|---|---|
| Package Firewall | Blocks packages Socket flags as malicious or compromised, at npm install or pip install time | On by default for every builder, nothing to set up |
| Dependency scans and Level 1 | Match new CVEs against your packages, automatically or on demand | Free |
| Auto-Protect patches | Agent prepares and tests a patch for a vulnerable dependency | Off until an admin sets a severity; billed as Agent work |
| Scan while you build | A lightweight review of the files Agent changes, for insecure patterns and hardcoded secrets | Automatic, no separate report |
| Publish checks | A scan before each publish. Block publishing of critical vulnerabilities stops critical findings from shipping | Setting in Publish > Advanced |
| Level 2: Security Agent | Maps routes and data flows, runs Semgrep and HoundDog.ai, then a model judges what is exploitable: SQL injection, XSS, CSRF, data in logs | Paid plans |
| Level 3: AI pentest | Level 2 plus a black-box test of the running Preview. On Clerk apps it tests signed out and as a synthetic user, plus a second synthetic user when it needs to check ownership | Extra plan and access requirements |
Run them. Then know their limits, which Replit's docs state plainly:
- Level 1 only reads your dependencies. A clean dependency scan says nothing about your own routes.
- Publish checks do not run Level 2 or Level 3. Passing one says nothing about your access rules either.
- Level 3 tests the Preview, not the published app. The published app runs with its own secrets, its own database and, with Clerk, its own user store. A clean Preview does not prove what strangers reach at your public URL.
- A source review reasons about code. Replit's own research found AI-only scans nondeterministic, which is why it pairs the model with static analysis (Semgrep, HoundDog.ai), and its docs say a scan is not a complete security review.
Replit security concerns, with concrete examples
These are the holes that remain after Replit's defaults, in the order we would check them. Each one is a type of mistake, not a specific app.
| Risk | What a stranger can do | How it happens on Replit |
|---|---|---|
| Route with no sign-in check | Read every record a list route returns, with no account | A route added without the auth check. Clerk's clerkMiddleware() alone only reads the session; the route must check getAuth(req).userId |
| Sign-in check, no owner check | Sign up, change an id in a request, then read or edit another customer's record | The query filters on the record id only. Replit's own login tutorial warns that two test customers may see each other's reservations |
| Admin page guarded in the browser | Call the admin API directly and skip the screen | The role check lives in a React component, not in the Express route |
| Secret key in the bundle | Charge cards, send email or run AI calls on your account | A key put in a VITE_ variable or a frontend file, both shipped to every visitor |
| AI route without limits | Run prompts on your Replit credits | Replit AI Integrations bills usage to you, and the route has no sign-in or rate limit |
| Unsigned Stripe webhook | Send a fake payment event that grants a paid plan | A manual Stripe setup whose handler never verifies the Stripe-Signature header |
| App published as Public by mistake | Open an internal tool or a beta full of real data | Apps in a personal workspace publish as Public by default |
How to check your Replit app
Six checks, from free and fast to thorough. The outside ones run against your own published URL only.
- 1
Check who can open the app
Open Tools > Publishing and look at Sharing. An internal tool or a beta with real data belongs in Password protected, Workspace only or Invite only, available on every plan since May 2026. Changing it means unpublishing, then publishing again.
- 2
Run the free scan, then the deep one
In Tools > Security Center, run Level 1: it is free and lists vulnerable packages. On a paid plan, run Level 2 for a source review, or Level 3 to add a test of the running Preview. Send accepted findings to Agent, rerun, then republish.
- 3
Search what you ship for keys
Build the app and search the output for secret key prefixes (command below), then search the project for
VITE_and read every value it exposes. Paste anything suspicious into the API key leak checker: it runs in your browser and says which keys are secret. - 4
Call your routes signed out
Use the app signed in with the Network tab open and note the
/api/routes that return personal data. Then call each one with no session. Every route that returns user data should answer401, and every AI route too. - 5
Repeat as a second account
Sign up twice, as Replit's own login tutorial recommends. As account B, open account A's records by their ids: a booking, an invoice, a profile, a file. Anything other than
403or404is an IDOR vulnerability. - 6
Check headers and leftovers
Paste your URL into the security headers checker. On your live site,
/.envand the.mapfile next to a JavaScript file should return nothing useful; the exposed .env guide says what to rotate if one does.
npm run build
grep -rlE "sk_live_|rk_live_|sk-proj-|sk-ant-|whsec_|postgres(ql)?://" dist 2>/dev/nulldist with the folder your frontend builds into. Any match is a key to rotate.# Your own app only. Signed out: expect 401, never records.
curl -i https://YOUR-APP.replit.app/api/bookings
# An AI route signed out: expect 401, never a model's answer
curl -i -X POST https://YOUR-APP.replit.app/api/chat \
-H "content-type: application/json" \
-d '{"message":"hello"}'200 with records from the first call means anyone on the internet can read them. A model's answer from the second means anyone can spend your credits.Fixes, with prompts for Agent
Agent writes these fixes well when the prompt names the rule. Paste the prompts, then read the diff before you accept it.
Every route: check the session, then the owner
Both route bugs have one fix. Refuse calls without a session, then put the signed-in user in the query, so a record that belongs to someone else is simply not found. Clerk recommends clerkMiddleware() with getAuth() for API routes; its older requireAuth() helper is deprecated and redirects instead of answering 401.
import { clerkMiddleware, getAuth } from "@clerk/express";
import { and, eq } from "drizzle-orm";
app.use(clerkMiddleware()); // reads the session, blocks nothing on its own
function requireUser(req, res, next) {
if (!getAuth(req).userId) return res.status(401).json({ error: "Sign in required" });
next();
}
// Before: any signed-in user reads any booking by changing the id
app.get("/api/bookings/:id", requireUser, async (req, res) => {
const [booking] = await db.select().from(bookings)
.where(eq(bookings.id, req.params.id));
res.json(booking);
});
// After: the owner is part of the query
app.get("/api/bookings/:id", requireUser, async (req, res) => {
const { userId } = getAuth(req);
const [booking] = await db.select().from(bookings)
.where(and(eq(bookings.id, req.params.id), eq(bookings.userId, userId)));
if (!booking) return res.status(404).end();
res.json(booking);
});Audit every route in the Express server.
1. List each route with its method, whether it requires sign-in,
and which table it reads or writes.
2. Every route that returns or changes user data must answer 401
without a session.
3. Every read, update and delete on a user-owned table must filter on
the signed-in user's id. Answer 404 when the record belongs to
someone else.
4. Admin routes must check the role in the server, not only in React.
Show me the list before and after, and a test plan with two accounts.Keys: only publishable keys reach the browser
Secret keys live in Secrets and are read in the server with process.env. The frontend only gets keys made to be public, such as Clerk's or Stripe's pk_ keys. A secret key that was ever in the bundle must be rotated at the provider: deleting it from the code does not take it back. The guide to API keys exposed in the frontend has the rotation steps per provider.
Find every API key, token or connection string in the frontend code,
in any VITE_ variable and in any file of the project. Move each secret
into Replit Secrets, read it only in the Express server, and add a
server route for the frontend to call instead. Then list the keys you
moved so I can rotate them at each provider.AI routes and the Stripe webhook
An AI route needs the same requireUser check plus a limit per user, so one account cannot drain your credits; the express-rate-limit example in Replit's security checklist is a start, and the unprotected AI endpoint guide goes further. A Stripe webhook is the one route that must stay open, so it proves itself with a signature instead of a session:
// Register before app.use(express.json()): Stripe signs the raw body
app.post("/api/stripe/webhook", express.raw({ type: "application/json" }), (req, res) => {
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers["stripe-signature"],
process.env.STRIPE_WEBHOOK_SECRET,
);
} catch {
return res.status(400).send("Invalid signature");
}
// handle event.type here, then answer quickly
res.json({ received: true });
});
app.use(express.json());express.json() must not parse it first. More in the Stripe webhook guide.Security headers
Agent apps need a server, so they publish on Autoscale or a Reserved VM: set the headers in your Express server. app.use(helmet()) (from the helmet package) adds a Content-Security-Policy, HSTS, X-Frame-Options and other protective headers in one line. Test the Preview after adding it: a strict policy can block scripts your app loads from other domains. A hand-built static deployment sets its headers in the .replit file instead.
Replit deployment security: the traps after the first fix
- A fix is not live until you republish. Agent edits the development copy, and dependency patches wait as pending republish. Then test the public URL: it reads its own values under Publishing > Adjust settings > Production app secrets.
- Remixes carry your history. Remixing a public app copies its files, configuration and checkpoint history; only secret values stay behind. A key you deleted from a file can still sit in an older checkpoint, so rotate it.
- Keys pasted into the Agent chat leave Secrets. Replit's own model says not to paste API keys or tokens into the chat: Agent can use a secret without seeing it, and a pasted key becomes an unmanaged copy. The same goes for a key your code prints to the logs. Rotate any key that went either way.
- Collaborators can read secret values. Multiplayer collaborators see them in the Secrets tool. Organization members without the Owner role cannot, but Replit notes they can print them from the environment. Give edit access only to people you would hand the keys to.
- The production connection string is a full credential. It works from any PostgreSQL client. If it lands in a chat, a ticket or a screenshot, the app owner or a workspace admin can use Regenerate credentials in the production database's Settings tab: the old string stops working at once. Apps moved off the legacy Neon development database keep the old string as
NEON_DATABASE_URLin Secrets: never share it either. - SQL you ran by hand stays in development. Publishing copies tables, views and row level security policies, but not functions, triggers or grants. A trigger or grant you added for safety is missing in production until you add it there.
Test the published app after every deploy
Replit's scans read your code and test your Preview. The open question is what a stranger reaches at your public URL, with production data, after each republish. That is what Keybrum attacks, and only on apps whose owner has proved ownership. On a Replit app it calls the API routes your JavaScript uses signed out and as a second account, checks AI routes and the Stripe webhook for missing protection, and looks for secret keys in the bundle, a served .env and missing security headers. Each finding comes with the request that worked, and the fix goes to your coding agent through MCP.
Replit app security checklist
- Sharing set to the narrowest option that fits; Public only for apps meant for everyone
- Security Center Level 1 run, plus Level 2 or 3 on a paid plan; findings fixed and republished
- Block publishing of critical vulnerabilities turned on in Publish > Advanced
- No secret key in frontend code, in a
VITE_variable, in any project file, in the Agent chat or in the logs - Every
/apiroute that touches user data answers401signed out - Every query on user data filters on the signed-in user's id, tested with two accounts
- Admin routes check the role in the server
- AI routes require sign-in and have a per-user limit
- The Stripe webhook verifies the signature with
constructEvent - Security headers sent by Express
- Errors show a generic message to users; details stay in the logs
- Production recovery window checked, and scheduled backups on for data you cannot lose
- Production connection string kept inside Replit, regenerated if it ever leaked
The same rules apply on every AI app builder. The vibe coding security checklist covers them across stacks, and vibe coding security risks explains why generated apps keep shipping the same holes.
Questions
Is Replit safe to use?
Yes, as a platform: Replit isolates environments, encrypts secrets and data, filters DDoS and holds a SOC 2 Type II attestation. Whether an app you build there is safe depends on its code and settings. Under Replit's own model, access control and pen testing of your app are your job.
Is Replit safe for production apps?
It can host them: production gets its own database with point-in-time recovery and its own secrets, and Agent cannot change that database. Before real users arrive, check the Sharing setting, run Security Center, test every route signed out and as a second account, and retest after each republish.
What are the main Replit security concerns?
Most come from the app, not the platform: API routes that skip the sign-in or owner check, secret keys shipped to the browser, AI routes anyone can call on your credits, and apps left Public that should be private.
Can people see my code or secrets on Replit?
Visitors of an app's cover page never see secret values, and people who remix your app get the secret names with empty values. Your files and checkpoint history do copy into a remix, so a key written in a file is exposed. Multiplayer collaborators can read secret values, and organization members without the Owner role can print them from the environment.
Does Replit scan my app for vulnerabilities?
Yes. Package Firewall and dependency scans are free, Agent checks the files it changes with Semgrep, and paid plans add a source review (Level 2) and a black-box test of the Preview (Level 3). Replit's docs say a scan is not a complete security review, so test the published app too.
Is a Replit deployment public by default?
In a personal workspace, yes: published apps default to Public, while organization workspaces default to a private option. Since May 2026 every plan can publish as Password protected, Workspace only or Invite only, unless a workspace admin turns an option off. Development URLs are private by default unless you turn off Private preview.
Did Replit Agent delete a production database?
Yes. In July 2025, during SaaStr founder Jason Lemkin's trial, the agent deleted his production database during a code freeze. Replit's CEO called it unacceptable and the company introduced separate development and production databases. Agent now reads production only through a read-only replica and cannot change it.
Sources
- 1.Replit shared responsibility model, Replit Docs
- 2.Security scan levels, Replit Docs
- 3.Project Security Center, Replit Docs
- 4.Agent security scans, Replit Docs
- 5.Black-box pen tests, Replit Docs
- 6.Package Firewall, Replit Docs
- 7.Development and production databases, Replit Docs
- 8.Connection details, Replit Docs
- 9.Data recovery, Replit Docs
- 10.Secrets, Replit Docs
- 11.Security checklist, Replit Docs
- 12.Changelog, January 16, 2026: Node.js security patch, Replit Docs
- 13.Who can access your app, Replit Docs
- 14.Users & Auth, Replit Docs
- 15.Clerk Auth, Replit Docs
- 16.Add login, Replit Docs
- 17.Remix an app, Replit Docs
- 18.Replit AI Integrations, Replit Docs
- 19.Changelog, May 8, 2026: private publishing for everyone, Replit Docs
- 20.How Replit Secures AI-Generated Code, Replit Blog
- 21.Clerk Express SDK reference, Clerk Docs
- 22.Env variables and modes, Vite documentation
- 23.Webhook signature verification, Stripe Docs
- 24.Replit makes vibe-y promise to stop its AI agents making vibe coding disasters, The Register
- 25.Thousands of AI 'vibe coding' apps may expose sensitive medical, business data, eWeek