You shipped your MVP this weekend. What did you leave exposed?
You did the thing. The deploy went green, the landing page loads, signup works, and you posted the link. That feeling is real and you earned it.
Here's the part nobody celebrates: the same speed that got you live is the speed that left doors open. You weren't sloppy. You were fast, and fast skips the boring review pass where someone checks what the deploy actually exposed to the public internet. That pass never happened. So the question is simple. What did you leave open?
The first thing a stranger checks
A stranger who finds your site doesn't read your code. They can't see it. They poke at the outside, fast, and most of the poking is automated.
The very first move is requesting files that shouldn't be there. A bot hits yoursite.com/.env, /.git/config, /backup.sql, /wp-config.php.bak, and a few dozen more, in the first second of finding you. Most of those return a 404 and the bot moves on. But MVPs ship these constantly, because the thing that made the file (a hosting default, a leftover dump, a .git directory copied up with the build) is invisible until someone asks for it directly.
If /.env returns 200, that's the whole game. Your database connection string, your API keys, your service_role JWT, sitting in a plain text response. No login. No exploit. Just a GET request anyone can type.
That service_role key bypasses every row-level security rule you wrote. Whoever has it reads and writes your entire database directly. The Stripe key moves your money. None of it shows up in your logs as an attack, because none of it is. It's just a download.
The five things MVPs leave open most
After the file probes, the same handful of issues show up over and over on freshly shipped products. A passive scan from outside surfaces all of them in one pass.
Walk down that list, because each one has a concrete consequence:
DEBUG=Truein production. A Django or Flask app left in debug mode renders a full stack trace on any error: file paths, settings, sometimes the secret key, sometimes a live SQL console (Werkzeug). An attacker triggers an error on purpose just to read it. Same story with Rails dev errors and a Whoops page on Laravel.- A live key in your JS bundle. A
sk_live_, anAKIA…, aghp_, all get inlined into the browser bundle when a framework prefix likeNEXT_PUBLIC_orVITE_is used by mistake. This is its own checkable thing, covered in the pre-launch pass every founder should run. - Source maps in prod. Ship your
.mapfiles and your minified bundle un-minifies itself for anyone. Your whole frontend, readable, including the comments you forgot were there. - An open admin panel. Adminer, phpMyAdmin, a Grafana or Strapi instance reachable on a subdomain with default or no credentials. Found by scanning common paths in seconds.
- Email anyone can spoof. No SPF record, or a DMARC policy of
p=none, means a stranger sends "reset your password" mail as you, and it lands in the inbox looking legitimate.
If you used an AI assistant to write most of this, the odds go up, not down. The model wrote a working feature and did not check what it exposed. That gap is its own subject in where vibe-coded apps leak.
Why you won't notice on your own
None of this trips an alarm. There's no failed login to see, no error in your dashboard, no email from your host. A correctly formed request for /.env is a normal request as far as your server is concerned. It returns the file and logs a 200, same as a page view.
So you can't find this by watching your app behave. The app behaves fine. You find it by looking at the same surface a stranger looks at, from the same place they stand, which is outside your perimeter with no access to anything. That's an awkward thing to do to your own product, because you know how it's supposed to work and you'll skim right past the file you forgot you deployed.
Check it from the outside in minutes
Every issue above sits on the outside of your perimeter, which means you can check it the same way the bot does: by asking. SurfaceCheckr requests the files a scanner would request, reads the JavaScript you actually shipped, probes the common admin paths, and inspects your headers, cookies, TLS, and DNS. All of it from the public internet, with no login and nothing installed. You point it at your URL and read the list of what came back.
Worth being clear on the edge of that. We see the surface a stranger sees, so we catch the 200 on /.env and the key in your bundle. We don't log in to check whether one of your users can read another's data, and we won't find the logic bug in your checkout flow. That deeper work is a pentest, and we draw the line out loud. The good news for a weekend MVP is that the things that get hit first are almost all out front, which is exactly where this looks.
You shipped fast. Spend three minutes seeing what shipped with it.
Find it before someone else does.
Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.