"Replit security" is two things worth keeping apart. The first is the Repl and its deployment: where secrets live, who sees your files, which URL is public and which port is exposed. The second is the code Replit Agent generates, usually an Express server with React and a Postgres database, which ships with the classic flaws of a backend written in a hurry. This guide covers both, with a block for the file the Agent reads on every request, a review prompt before deploying and the checks from outside.
Part 1: securing your Repl and your deployment
Secrets: the Secrets tab, not the code
Replit has a secrets manager that stores variables encrypted and exposes them to the process as environment variables, without them appearing in any file. It is the only right place for API keys, the database connection string and the session secret. The usual mistake is that the Agent, or you in a hurry, writes them into a .env, a config.json or straight into the code. Those files are part of the Repl: they are visible in a public Repl, copied on fork and deployed.
Public Repls and the development URL
A public Repl shows all its files to anyone, including the ones you forgot: backups, an old .env, data exports. Before making it public, review the whole tree. And while the Repl is running, the .replit.dev development URL answers whoever has it; it is not a private environment, it is a server on the internet with your test data.
Deployments
Deployment publishes the app on a .replit.app subdomain or your domain, with automatic TLS. The deployment's environment variables are configured separately from development's, so check that production does not point at the test database. Only the port you declare is exposed, but everything that port serves is public: API routes, static files and whatever the server returns by mistake. Replit adds no security headers; your server sets them.
Built-in database and authentication
The built-in Postgres database hands you its connection string as a secret; never copy it into a file. If you use Replit Auth, Replit manages the session and your code receives the already identified user, but every route still has to check that there is a session and that this user may do what they ask.
Part 2: the flaws the Agent puts into your code
- Secrets in files. The OpenAI key or the Postgres string in
.env, in a constant or in aconfig.jsonserved as static. - API routes without authentication. The dashboard checks the session in React;
/api/usersanswers anyone. - Static folders that are too wide.
express.staticpointing at the project root servespackage.json,.replit, the server code and any forgotten file. And without anindex.html, some servers list the directory. - Debug and seed routes.
/api/debug,/api/seed,/api/resetcreated for testing and deployed. - Open CORS with credentials.
cors()with no options plus session cookies: any website acts on behalf of your users. - SQL queries by concatenation. A string built with what arrives from the form instead of parameters.
- File uploads to disk served as is. Any user uploads a file and any visitor downloads it by name.
- No rate limit, no headers. An endpoint that calls a paid model with no cap, and not one security header.
A block so the Agent always applies it
Replit Agent reads your project's replit.md file as permanent context. Add this section:
## Security rules
- Keys, the database string and the session secret are read from process.env and live in the Secrets tab. Never in .env, config.json or the code.
- Every API route that reads or writes data checks the user's session and permissions on the server. Checks in React do not count.
- express.static only serves the frontend build folder or public/, never the project root.
- No debug, seed or reset routes in production.
- CORS with an explicit list of origins; never the wildcard with credentials.
- All SQL queries use parameters. All form input is validated on the server.
- Uploaded files are stored outside the public folder and served only after checking permissions.
- Security headers with helmet and a rate limit on routes that cost money.
And the headers in Express, in two lines:
import helmet from 'helmet';
app.use(helmet());
app.use(helmet.hsts({ maxAge: 63072000, includeSubDomains: true, preload: true }));
A review prompt before you deploy
Review the security of this project and do not change anything yet. Answer with a list:
1. Keys, connection strings or secrets written in files or in the code, with file and line.
2. API routes that read or write data without checking the session, and debug, seed or reset routes.
3. Folders served as static and which files they expose.
4. CORS and session cookie configuration.
5. SQL queries built by concatenation and unvalidated input.
6. Where uploaded files are stored and how they are served.
7. Whether security headers and a rate limit exist.
For each point, propose the exact change and wait for my confirmation.
Check the result from the outside
curl -sI https://yourdomain.com | grep -iE "strict-transport|x-frame|x-content-type|content-security"
for p in .env .replit package.json config.json .git/config server.js uploads/; do printf "%-14s " "$p"; curl -s -o /dev/null -w "%{http_code}\n" "https://yourdomain.com/$p"; done
curl -s -o /dev/null -w "%{http_code}\n" https://yourdomain.com/api/users
Expected: headers present, 404 on the whole file list and a 401 or 403 on the API route without a session. A 200 on package.json or .replit means you are serving the project root. Scanaris runs these checks and about forty more in 30 seconds: it looks for exposed files and directory listings, endpoints that answer without a session, secrets in the JavaScript, headers, CORS, cookies and TLS, and gives you a fix prompt for each failure to paste into the Agent chat. And it can rescan every day, because a regeneration can bring back a flaw you had already fixed.
Frequently asked questions
Are Secrets tab values visible in a public Repl?
No, secrets are not shown and are not copied on fork. What is visible is everything else: files, code and any key written in them instead of in Secrets.
Is the development URL private?
No. While the Repl runs, it answers anyone who has the link. Do not use it with real data or share it thinking only you can see it.
Does Replit set security headers on deployments?
No. It provides TLS and the domain, but the headers are sent by your server. With Express, helmet adds them in two lines; with other frameworks, their equivalent.