Verified proof card
Directly observed · high confidence · evidence redacted
Sample report
This is a made-up report for a domain that does not exist — but the findings are the ones we see most often in real scans. Fully expanded, with the location, the evidence and a ready-made fix. This is exactly what you get for your own domain after unlocking.
Made-up data. The domain beispiel-app.de does not exist — a sample report about someone else’s real site would be publishing their weaknesses.
Security report for
Scanned on 1 August 2026 · Automatically deleted on 30 October 2026
Security grade
Fix this soon
2
critical
1
high
2
medium
1
low
1
info
Badge preview · Example
Not active — fictional sample report
Directly observed · high confidence · evidence redacted
Security goal, requirements, negative test and re-test
2 fixed · 1 unchanged · 0 regressions
Deep scan current · source scan missing · ready with limits
Protection target session:cookie agrees on both layers
Example: last run successful · next check in 6 days
An OpenAI key sits in plain text in your frontend bundle. Any visitor can read it, and automated bots comb public bundles looking for exactly this. The key counts as compromised the moment it was shipped — even if you replace the bundle now.
Revoke the key immediately at platform.openai.com/api-keys — not later; the old one is irreversibly public. Then: the call belongs on the server, not in the browser. Add your own route (an edge function or /api/chat) that holds the key server-side and forwards the request. The frontend then only calls your route. `dangerouslyAllowBrowser: true` is the SDK telling you this path was never intended.
We queried the table using the public anon key from your frontend and got rows back. That means anyone who opens your site can download the entire table — including other users’ rows.
In the Supabase console under Authentication → Policies for the `profiles` table: ```sql ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; CREATE POLICY "Read own profile" ON profiles FOR SELECT USING (auth.uid() = id); CREATE POLICY "Update own profile" ON profiles FOR UPDATE USING (auth.uid() = id); ``` Note: `ENABLE ROW LEVEL SECURITY` on its own blocks everything — without a policy your own app loses access too. The two belong together. Then scan again — this check is the proof that it worked.
Your source maps sit next to the bundle and can be fetched without signing in. That reconstructs your unbuilt original code — filenames, comments and your project’s folder structure included.
In `vite.config.ts`:
```ts
export default defineConfig({
build: { sourcemap: false },
});
```
For Next.js: `productionBrowserSourceMaps: false` (that is already the default — check whether something set it to `true`).
Then rebuild and redeploy. Delete existing `.map` files on the server: a new build does not necessarily remove them.Without a Content-Security-Policy, injected code in your page can load arbitrary scripts. That is the difference between a harmless and an exploited XSS hole.
A starting point for a typical SPA: ``` Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none' ``` Roll it out as `Content-Security-Policy-Report-Only` first and watch the browser console for what would be blocked. Only switch to the enforcing header once nothing important shows up.
Without a Referrer-Policy the browser sends your page’s full address to third-party servers whenever someone clicks an outbound link — query parameters included.
Add the header: ``` Referrer-Policy: strict-origin-when-cross-origin ``` This is what modern browsers already default to — setting it explicitly makes the behaviour independent of the visitor’s browser.
Without DMARC anyone can send email using your sender address. For phishing aimed at your own users that is half the work done — and it hits exactly the people who trust you.
Add a TXT record with the name `_dmarc`: ``` v=DMARC1; p=none; rua=mailto:dmarc@beispiel-app.de ``` Start with `p=none` — it rejects nothing yet but collects reports on who sends in your name. Once the reports look clean, move to `p=quarantine` and later `p=reject`. Starting at `p=reject` can make your own mail from newsletters or billing systems undeliverable.
Detected from the bundle structure and the addresses being called. This is not a defect — it decides which deep checks make sense for your app at all.
Nothing to do. We list it because it determines which checks we run for you — and because you should know what is visible about your setup from the outside.
The scan is free and takes about twenty seconds. You see straight away how many findings there are and how serious they are.
Scan your own app for free