A Replit app most often exposes its database in one of two ways: a plain .env file committed to a public repl, where anyone can read every file including that one, or database credentials placed in client-side code that ships to users. On a public Replit repl, files are visible to everyone, so a .env is not private. The fix is to store secrets in Replit Secrets, which are kept separate from your files, and to make the repl private if the code itself is sensitive. Then keep database access on the server, enable Row Level Security if a public key can reach your data, and rotate any credential that was exposed.
Short answer
A Replit database gets exposed when secrets live in files a public repl reveals, or when database access happens in client code. Per Replit's Secrets documentation, secrets belong in Replit Secrets, which are stored separately from your files and injected as environment variables, rather than in a .env that a public repl exposes. Keep database credentials and queries on the server, not in the client. If you use a service like Supabase where a public key reaches the database, enable Row Level Security and test it, per Supabase's RLS guidance. Finally, rotate any credential that was exposed, since a leaked one should be treated as compromised.
How a Replit app exposes its database
There are two common exposure paths, and they are different problems. The first is secrets sitting in files that a public repl makes readable: a committed .env, a config file, or a hardcoded connection string. Because a public repl shows all of its files to anyone, any secret in those files is effectively published, including a database URL or password.
The second path is database access from the client. If your app connects to the database directly from browser or client code, the credentials or keys needed for that connection ship to users, who can read them. Both paths end with someone outside your team holding what they need to reach your data, so securing a Replit app means closing both: keep secrets out of visible files, and keep database access on the server.
Are .env files public on Replit?
On a public repl, effectively yes. A public Replit repl exposes its entire file tree to anyone who views it, so a .env file committed there is readable, and any secret inside it is exposed. This surprises developers who assume .env is special, but Replit treats it as just another file, and a public repl publishes files.
The safe alternative is Replit Secrets. Secrets you add through Replit's Secrets feature are stored separately from your files, are not shown in the file tree, and are injected into your app as environment variables at runtime, so they stay private even on a public repl. If your code is itself sensitive, you can also make the repl private, but the more important habit is to never put a real secret in a file and instead always use Secrets.
Use Replit Secrets instead of a .env file
Moving your secrets into Replit Secrets is the core fix. Add each secret, such as a database URL, an API key, or a service credential, through the Secrets feature rather than writing it into a .env or source file, and read it in your code through the environment variable it provides. This keeps the value out of every file a repl could reveal while still making it available to your running app.
Do this for every secret, not just the obvious ones. A database connection string, a third-party API key, and a signing secret all belong in Secrets, and none belong in a committed file. If you previously kept them in a .env, move them to Secrets, remove them from the file, and rotate them, since anything that lived in a public repl should be considered already exposed.
Keep database access server-side
The second fix is architectural: keep database credentials and queries on the server, not in the client. Your app's frontend should call your own server code, which holds the credentials and talks to the database, rather than connecting to the database directly from the browser with credentials that ship to the user. This way the secret never leaves the server, no matter who inspects the client.
Where you use a backend service whose model is a public client key, such as Supabase, the client can talk to the service directly, but only because access is governed by policies rather than by hiding a credential. In that case the equivalent of server-side protection is Row Level Security, which constrains what the public key can do. Either way, the principle is the same: nothing that grants broad database access should ship to the client.
How to set up RLS
If your Replit app uses a service like Supabase where a public key reaches the database, Row Level Security is what keeps that access safe. Enable RLS on every table the client can reach, then write policies that grant each role only what it needs, for example letting users read and write only their own rows and giving the anonymous role access only to genuinely public data. Enable RLS first, since a table with it off is fully open to the public key.
Then verify the policies rather than assuming them. Query your tables as the anonymous role and confirm you cannot read or modify data you should not, because a policy that is too permissive leaves you no safer than none. This testing is the step that turns RLS from a box you ticked into protection you have confirmed, and it is essential before an app with a public key holds real data.
Containment: rotate exposed credentials
If a credential was already exposed, whether in a public repl or in client code, rotate it. Treat any database URL, password, API key, or service credential that was reachable as compromised, and issue a new one, because the exposed value may already have been copied. Rotation is the step that actually protects you, since removing the file or making the repl private afterward does not undo exposure that already happened.
Pair rotation with an assessment of what was reachable. Determine which credentials were exposed and for how long, and what data they could access, so you know whether you also have a disclosure obligation. Then confirm the new credentials live only in Replit Secrets and server code, so the same exposure does not recur.
Fixes compared
The exposures map to specific fixes. The table below pairs each one with its remedy.
| Exposure | What is wrong | Fix |
|---|---|---|
| .env in a public repl | Every file is readable, including secrets | Use Replit Secrets, or make the repl private |
| DB credentials in client code | The connection string ships to users | Keep database access on the server |
| Missing RLS with a public key | The public key reaches all data | Enable and test Row Level Security |
| Hardcoded key in a file | The secret is committed | Move it to Secrets and rotate it |
| Sensitive code in a public repl | The source itself is exposed | Make the repl private |
Read the table against your app to find which exposures apply. Most Replit database leaks come from the first two rows, secrets in visible files and database access in the client, so those are where to look first.
Securing checklist
A short sequence closes the common gaps. The checklist below covers it.
| Check | Action | Done? |
|---|---|---|
| Move to Secrets | Put every secret in Replit Secrets, not a .env | [ ] |
| Repl visibility | Make the repl private if the code is sensitive | [ ] |
| Server-side database | Keep credentials and queries off the client | [ ] |
| Enable RLS | Turn on Row Level Security and test as the anon role | [ ] |
| Rotate credentials | Rotate anything that was exposed | [ ] |
The two that resolve most cases are moving secrets into Replit Secrets and keeping database access server-side, because together they stop both exposure paths. Rotating exposed credentials is the containment step that makes the fix real rather than cosmetic.
Verify with a scan
After securing the backend, it is worth verifying that no secret still ships in the app you deploy, since a leftover hardcoded credential or a client-side database key can persist even after you move things to Secrets. Verification is what confirms the fix reached the shipped build.
A scanner like PTKD.com analyzes your app build and reports findings ordered by severity and mapped to OWASP MASVS, including secrets embedded in the app, so you can confirm no database credential or key leaked into what you deploy. To be clear about the boundary: PTKD does not manage your Replit Secrets or configure RLS. It checks the built app for exposed secrets, which complements moving credentials server-side and locking down database access.
What to take away
- A Replit app exposes its database mainly through secrets in files a public repl reveals, or database access in client code.
- On a public repl every file is readable, so a .env is not private; store secrets in Replit Secrets, which stay private even on a public repl.
- Keep database credentials and queries on the server, and never ship anything that grants broad database access to the client.
- If a public key reaches the database, enable and test Row Level Security so the key is constrained by policy.
- Rotate any exposed credential, and verify with PTKD.com that no secret shipped in your deployed app.




