The 10-minute security pass every solo founder should run before launch
You're close. The product works, the pricing page is done, and you're picking a launch day. Before you pick it, give the thing 10 minutes of adversarial attention.
This isn't a security audit or a sprint. It's a quick pass, the way you'd glance at a checkout flow one last time before sending the email. The reason to do it now is purely economic: the cheapest time to find a hole is before your first user does. After launch, the same finding costs you a rotated key, an incident note, and a customer who watched it happen. Before launch, it costs you 10 minutes and nobody knows.
What "before your first user" actually buys you
Your first user is rarely the only one watching. The moment you post a public URL, automated crawlers find it, often within minutes, and they don't read your roadmap. They request files, fingerprint your stack, and check the boring stuff you were too busy to check.
So the gap you care about is the window between "URL is public" and "I noticed the problem." Run the pass before launch and that window is zero. Run it after, and the window is however long it takes a customer to email you, which is also however long an attacker had a clean shot.
The pass below is everything a stranger checks in their first look. You're just looking first.
The 10-minute pass
Open a terminal and your browser. Point each check at your real production URL, not localhost.
1. Ask for files that shouldn't exist (2 min). Request each of these and confirm you get a 404, not a 200:
/.env /.git/config /backup.sql
/.aws/credentials /wp-config.php.bak /config.json
A 200 on any of them is a credential leak. /.git/config is the quiet one: if it's reachable, your whole repository history is downloadable, including secrets you committed and "removed" three commits later. Git keeps them.
2. Search your own JS bundle (2 min). Open the site, press F12, and run a global search (Ctrl+Shift+F) across loaded files for sk_live_, AKIA, ghp_, service_role, and -----BEGIN. Any hit is a key you shipped to every visitor. While you're there, check whether .map files load. Source maps in prod hand an attacker your un-minified frontend.
3. Trigger an error on purpose (1 min). Hit a route that doesn't exist, post bad data to a form. If you get a stack trace, a Werkzeug console, a Rails error page, or anything that says DEBUG, your app is leaking its own internals. Production should return a clean error page and nothing else.
4. Check the headers and the cookie (2 min). Load the site, open the Network tab, click the document request. Look for Strict-Transport-Security, a Content-Security-Policy, and on your session cookie, both HttpOnly and Secure. A session cookie without HttpOnly can be read by any injected script; one missing Secure rides along over plain HTTP.
5. Look at your email DNS (2 min). Check that your domain has an SPF record and a DMARC record stronger than p=none. With p=none, a stranger sends mail as your domain and it isn't rejected. The phishing version of your launch email is a real risk, and it's a one-record fix.
v=spf1 include:_spf.google.com -all
v=DMARC1; p=reject; rua=mailto:[email protected]
Use -all and p=reject. A ~all softfail and a p=none policy both publish a record that tells receivers to do nothing about forgeries, which is the same as having no policy at all.
When the cookie or header check fails
Most of step 4 and 5 are one-line fixes in config, and the change is genuinely small. Here's the cookie case, vulnerable and fixed, so you can see how little moves:
Set-Cookie: session=a1b2c3; Path=/ # anyone's injected script can read document.cookie # and the cookie travels over plain HTTP
The pattern repeats. The HTTPS redirect is a config flag. HSTS is one header. SPF and DMARC are TXT records. None of this is a rewrite. It's a checklist, and the work is finding the items, not fixing them.
Run it again automatically
Ten minutes by hand works once. The trouble is that "before launch" isn't a single moment, it's every deploy after it. A future commit re-enables debug mode, a teammate adds an admin tool on a subdomain, a dependency bump changes your headers. The pass goes stale the day you finish it.
That's the part to hand off. SurfaceCheckr runs this exact outside-in pass on a schedule and tells you when something that was closed opens back up, without touching your backend or your data. The honest limit is the same one that applies to your manual pass: it sees what an attacker sees from outside, so it won't replace a pentest of your authenticated routes. For everything on the perimeter, it's the same look you'd do by hand, just done every time you ship.
If you only do one thing before launch day, do step 1. A 200 on /.env is the cheapest catastrophe to prevent and the most expensive to discover late. For the wider list of what a fresh deploy leaves open, the MVP exposure rundown covers the rest.
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.