What we found when we audited ourselves.
A real, severity-tagged code and configuration security review for small-business websites. $199 quick scan or $499 full audit, delivered in 1–2 business days. Below: every finding from our own most recent audit, real CVE numbers and all.
What does a security audit cover?
Eight categories, every time. We do them in the same order on every audit so the deliverable is consistent — and so we never miss a class of finding because the project was unusual.
Dependency CVEs
Every npm / pip / composer / gem package in your tree gets checked against the public vulnerability database. We separate "must fix" from "transitive, no patched version" with a recommended next step for each.
Security headers
CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy. Probed live against your production domain — we show you the exact response and what is missing.
API input validation
Every API route gets a read-through for unvalidated body / query / params. We flag anywhere a string from the client flows into a database query, an external API call, a file path, or a template literal that could be injected.
Rate-limiting coverage
Public endpoints that mutate state, send email, or burn CPU on cryptographic operations need rate limits. We list every endpoint that does not have one and what limit is appropriate (per IP, per email, per hour).
Webhook signatures
Stripe, Lemon Squeezy, Resend, Twilio, GitHub — every webhook handler gets verified to use signature checking with constant-time comparison. Misconfigured webhook verification is one of the top "looks fine, is exploitable" patterns.
File uploads
MIME allowlist, extension cross-check, max size, virus scanning, storage-bucket privacy, signed-URL expiry, filename entropy. The youth-camp R2 bucket bug below was caught by this exact checklist.
Secrets in git history
A full `git log --all -p -S` sweep for live API key patterns (sk_live_, re_*, AKIA*, eyJ*) across every branch and tag. We catch the keys committed by an intern in 2022 that nobody ever rotated.
Third-party integrations
Every external SDK and embedded tag gets reviewed for posture: are CSP origins narrow, are tags consent-gated, do we leak PII to analytics, is the chat widget actually configured correctly. (Ours was not — see below.)
Why we audited our own site first — and what we found.
Before we sold this service to anyone, we ran the full audit method against cipherforces.com — same Next.js + React + Tailwind stack many of our clients run, same kinds of integrations (Stripe, Resend, Airtable, Cloudflare R2). The audit ran on 2026-05-26. Some of what we found is below. Everything is severity-tagged. Every code reference is a real file:line. No invented CVE numbers.
The point isn’t to be embarrassed — it’s to show you what a real audit looks like in practice. Your audit will surface findings like these, tagged with the same severities, framed the same way.
Next.js 16.2.1 had five HIGH CVEs
Server Components DoS (GHSA-q4gf-8mx6-v5v3 and GHSA-8h8q-6873-q5fj, both CVSS 7.5), middleware/proxy bypass on segment-prefetch (GHSA-26hh-7cqf-hhc6, CVSS 7.5), redirect cache poisoning (GHSA-3g8h-86w9-wvmq), and an App Router CSP-nonce XSS (GHSA-ffhc-5mcf-pf4q). We bumped to 16.2.6, re-ran the production build to confirm no regressions, and shipped the patch the same day.
Stripe webhook had no rate-limit
The signature verification gates it correctly — unverified payloads bounce. But a flood of unverifiable signatures still burns CPU on every `constructEvent` call. We mirrored the Lemon Squeezy pattern and added a 30-request-per-IP-per-60-seconds limit keyed on `webhook-stripe:${ip}`. Five lines of code, one new edge case in the test suite.
Airtable formula injection on /api/upload/print
Our Zod schema for the `orderId` field was `z.string().min(1).max(200)` — which accepts apostrophes that break the `RECORD_ID() = '${orderId}'` formula and let a crafted ID query an arbitrary record. We tightened the schema to `.regex(/^(rec[A-Za-z0-9]{14,}|cs_[A-Za-z0-9_]+)$/)` so only real Airtable record IDs or Stripe session IDs pass.
Youth-camp R2 bucket was publicly readable
Submission IDs were ~36 bits of entropy and the bucket served from a `pub-*.r2.dev` URL. Payment screenshots and signatures of minors were technically guessable. We flipped the bucket to private, switched to short-lived signed URLs in the n8n payload, and regenerated submission IDs with `crypto.randomUUID()` for ~122 bits of entropy.
Tawk.to chat widget was broken in production
The embed URL was constructed as `embed.tawk.to/{propertyId}/{widgetId}/default` — returning 404 on every page load. Tawk's current spec is exactly two path segments. We probed all three variants live, confirmed the two-segment URL returned 200 OK, and shipped the fix. The previous live-chat conversion path had been dead for an unknown number of weeks.
PII in console logs on /api/proposal
The proposal endpoint was destructuring the request body raw and then `console.log(name, email, phone, website, budget, …)` on every submission. Vercel function logs are retained for 30 days. We added a Zod schema mirroring `/api/contact` and dropped the PII log — the request still gets traced, just without the personal data.
Source: SECURITY_AUDIT_LOG.md in the cipherforces repo, 2026-05-26 sweep. The full audit log contains 28 findings; six are excerpted here.
What gets delivered?
Five concrete artifacts. You can commit the docs straight into your repo, forward them to your dev team, or hand them to a contractor — they read cleanly to anyone technical.
Full audit log
Every finding gets a severity tag (CRITICAL / HIGH / MEDIUM / LOW / INFO), a file:line reference, a concise explanation of why it matters, and a recommended fix. Delivered as a Markdown doc you can commit straight into your repo as `SECURITY_AUDIT_LOG.md`.
Prioritized pending-fixes doc
A second doc — `SECURITY_PENDING.md` — that re-orders the audit log by execution priority: what to fix today, this week, this month, eventually. Each item has an estimated effort in minutes so you can plan around it.
PR-ready code fixes
For findings inside our wheelhouse (Next.js, React, Node), we deliver the actual code diff as either applied PRs (if you give us write access) or copy-paste-ready patches in the pending doc. No homework for you to do.
Hosting + env hardening notes
A short addendum covering Vercel / Cloudflare / Netlify project settings (env-var hygiene, region pinning, function timeout safety), DNS records (SPF, DKIM, DMARC alignment), and CSP origin pruning. Five to ten concrete configuration changes, none of which require a code deploy.
Optional /api/health probe endpoint
On request we add a small aggregate health-check endpoint that pings every external integration (Stripe, Resend, your database, Redis if used) and returns a JSON status doc. Wires straight into uptime monitors like UptimeRobot or BetterStack.
How long does it take?
Standard turnaround is 1–2 business days. Larger sites or sites with multiple custom integrations run 3–5 business days — we tell you up front before we start the meter. Same-day quick scans are available for an extra $100 if you have a launch or compliance deadline.
Quick Scan
Headers, TLS, dependency CVEs, obvious misconfigurations, public-surface probing. Right-sized for static sites, marketing pages, and sites under ~30 routes.
- Live security-header probe
- Full dependency CVE scan
- TLS + certificate posture
- Public-surface probing
- Severity-tagged finding list
Full Audit
RecommendedEverything in Quick Scan plus a full code review. Right-sized for any site with a backend, API routes, payment integration, webhooks, or file uploads.
- Everything in Quick Scan
- Full code review on input validation
- Webhook + rate-limit coverage map
- Secrets-in-git-history sweep
- PR-ready code-fix diffs
- Prioritized SECURITY_PENDING.md doc
- Vercel / Cloudflare env hardening notes
Code-fix execution after the audit: $85/hr for findings inside our wheelhouse (Next.js / React / Node / TypeScript / general web). Most full audits surface 3–6 fixable items in that bucket — usually 4–10 hours of work total. Larger refactors get quoted as a separate project.
What if we find something critical?
We stop and call. If a finding is in the CRITICAL bucket — actively-exploitable credential leak, live RCE, exposed production database, payment-data exfiltration vector — the rest of the audit pauses. Daniel reaches out within 4 business hours, walks you through what we found, and gives you a recommended remediation timeline.
Hot-patch the same day if you want. For critical findings inside our wheelhouse, we can write and ship the patch the same day at our after-hours rate ($150/hr). For findings outside our stack we hand you the exact remediation instructions and stand by while your team executes — no extra charge for the hand-holding.
No "we found something, pay us to know what." We do not gate critical findings behind an upsell. If your site is on fire, you are going to know about it inside the first phone call. The follow-up paid work is the fix, not the disclosure.
Common security audit questions.
Do you need access to our server or code?
It depends on the scope. For the quick scan we usually only need your public site URL and read-only access to your code repo or hosting dashboard if you have one — we use that to check dependency versions and security headers. For a full audit we ask for read-only access to the codebase, environment-variable names (not values), and a list of any third-party integrations (Stripe, Resend, Airtable, etc.). We never need write access.
Will the audit cause any downtime?
No. The audit is read-only and runs against your public surface plus your code. We don't deploy anything, change DNS, or push commits during the audit itself. If we find a critical issue and you ask us to hot-patch it, that fix will deploy through your normal pipeline like any other change.
What kinds of sites do you audit?
Production Next.js / React / Node / Astro / SvelteKit sites are our strongest suit — that is what we build day-to-day, including this site. We also audit static sites, Webflow, Framer, and Shopify storefronts. The audit method is the same; the findings shift with the stack.
Can you audit a WordPress / Shopify / Wix site?
Yes for the public-facing security posture (headers, TLS, mixed content, third-party tag bloat, leaked admin paths, plugin-version disclosure). For WordPress we also scan installed plugins and themes against the WPScan vulnerability database. We do not modify the platform itself — if a Wix or Shopify site has a vendor-side issue we surface it and you escalate to the vendor.
How is this different from a penetration test?
A penetration test simulates an attacker against your live production environment — it is adversarial, time-boxed, and usually requires a formal Rules of Engagement document. Our security audit is a code + configuration review plus passive probing of your public surface. It catches the same classes of issue (dependency CVEs, missing headers, weak input validation, leaked secrets, misconfigured third-party tags) at a fraction of the cost. If after our audit you still want a full pen-test, we can refer you to a partner — but most small businesses do not need one until they handle payment data at scale or have a compliance requirement.