Insights › Builder guides
Replit app security: what your deployment exposes that your code doesn't
Replit takes an app from idea to a live URL without leaving the tab, but the deployed surface often exposes debug endpoints, env var leaks and missing headers that a code review can't catch. Here's what to check on the live URL before you share it.
Aug 8, 2026 · 7 min read
The short version
Replit's development environment and its production deployment are different machines with different configurations. What ran fine in the workspace can leak debug routes, expose environment variables, or serve over HTTP once deployed — and those gaps are only visible by loading the live URL. Every check below is on the deployed app, not the repo.
1. The redirect chain: domain, DNS and SSL
A Replit deployment gets a *.replit.app subdomain. The moment you add a custom domain, you own the redirect chain: the bare domain to www, HTTP to HTTPS, the Replit preview to the canonical domain. Actuant follows the real redirect chain your deployment returns and checks:
- Every variant resolves. Bare domain,
www, HTTP, HTTPS — all of them should reach your app with a single 301 to the canonical URL, not a chain of redirects or a dead end. - HTTP redirects to HTTPS with HSTS. A first-time visitor over HTTP should get a 301 to HTTPS, and the HSTS header should pin HTTPS for every future visit.
- No expired certificates. An expiring or misconfigured SSL cert is a silent outage — browsers show a full-page warning that most visitors close instead of bypassing.
2. Debug routes and development leftovers
Replit's dev environment often exposes routes like /debug, /api/test, or /graphql with introspection enabled. These can survive the deploy if they're not behind a production flag. Load your live URL and check for endpoints that return stack traces, database schemas, or internal config.
Also check for Replit-specific files served publicly: .replit, replit.nix, or config files at the root. Anything a visitor can request by guessing the path is part of your surface.
3. Security headers
Replit's deployment proxy adds some headers, but the security-critical ones — CSP, HSTS, frame guard, referrer policy — must come from your application. A generated deploy rarely sets any of them:
- Content-Security-Policy. Without it, an injected script runs with full access to your domain. Actuant grades the CSP's contents, not just its presence —
unsafe-inlineandunsafe-evalget flagged. - Strict-Transport-Security. The
max-agemust be at least one year (31536000) andincludeSubDomainsshould be set. Anything shorter is a token gesture. - X-Frame-Options or CSP
frame-ancestors. Prevents your app from being loaded in an invisible iframe on an attacker's page. - X-Content-Type-Options: nosniff. Stops the browser from guessing MIME types, which can turn an uploaded text file into an executable script.
4. Environment variable exposure
Replit Secrets are encrypted at rest, but if your app echoes an env var in an error message, includes it in a client bundle, or exposes it through a debug endpoint, it's public. Actuant scans the rendered page and the JavaScript bundles for strings that look like API keys, database URLs, or JWT secrets. This is one of the highest-severity findings because it can't be undone — a leaked key must be rotated, not just hidden.
5. Google and AI crawlability
If your Replit app is a client-rendered SPA, the indexing problem applies in full: Googlebot and AI crawlers see an empty HTML shell before JavaScript runs. The same four-fix sequence applies — serve real HTML, set metadata, add a sitemap, verify in Search Console. See the Lovable indexing guide for the specific steps; the cause is identical.
6. Supabase RLS, if you're using it
Many Replit apps use Supabase for the backend. Row-Level Security is the gate that decides whether an unauthenticated request can read your users' data. If RLS is disabled on a table, anyone with the anon key can query it. Actuant probes the Supabase REST API from outside — it sends an unauthenticated request and reports whether it got rows back. A pass means RLS is enabled; a fail means your data is publicly readable.
How to run these checks yourself
- 1
Load the live URL in an incognito window
This is the closest approximation of what a first-time visitor sees — no cookies, no cached redirects, no logged-in state.
- 2
View source, not inspect
Cmd+U shows the raw HTML the server sent. If the body is an empty root element, Googlebot's first pass sees nothing.
- 3
Run a quick header check
curl -I https://yourapp.comshows the redirect chain and security headers in one line. Look for HSTS, CSP, and X-Frame-Options. - 4
Request a few common debug paths
/debug,/api,/graphql,/.env. If any return data instead of a 404, they need to be gated behind a production flag.
Every check in this article maps to a real check in Actuant's audit engine. It loads the deployed URL in a real browser, follows the redirect chain, grades every header, probes for data leaks, and reports each finding with the exact URL, header or config line to fix.
Keep reading
Content-Security-Policy: what it protects, how to write one, and the mistake that makes it useless
A Content-Security-Policy tells the browser which scripts, styles and connections to trust — it's your primary defense against XSS. A generated app ships with none. Here's how to write one that's strong enough to matter and test it without breaking anything.
Security headers: the six your app needs and what each one protects
Security headers are HTTP response headers that tell the browser how to defend your visitors. A generated deploy sets none of them. Here are the six that matter, what each one does, and how to check they're actually being served.