The attack surface any stranger already has on Pawpal (demo)
Pawpal – Trusted pet sitters near you is built with Lovable on Supabase, calling OpenAI from the browser.
- CVE-2025-48757
- 5432
- 6379
- 2375
- JWT crack
- IDOR
- SQLi
- .env / .git
- 1 JavaScript file any attacker can already download and read.Same files a visitor's browser is handed: backends, table names, API routes and any key that was shipped to the client.
- A Supabase public key is in the code, next to app_settings, bookings, messages, payouts, profiles, reviews.CVE-2025-48757 is the missing-RLS case: anyone who has the public key can read the database. The preview names the tables. The attack reads them.
- OpenAI, Supabase are readable in the public code.The attack checks whether they still work, with a free read-only call. The key values are not shown here.
- The public address may not be the server. The attack looks up the origin, then greets the ports that should never face the internet.Postgres 5432, MySQL 3306, MongoDB 27017, Redis 6379, Elasticsearch 9200, Docker 2375, etcd 2379, and admin consoles. One greeting per port. No password is sent.
Angles the full attack will take
102 attacks apply to this stack- Read, add and change rows in 6 tables named in the code
- CVE-2025-48757
- RLS
Anonymous first, then as a brand-new account that owns nothing. This is the CVE-2025-48757 class: missing Row Level Security. Write tests are built so nothing is written. - Crack a weak or default JWT secret offline, then mint a service_role token
- JWT
The public anon key's signature is checked against well-known defaults. If one matches, the attack signs an admin token and confirms it with one read-only call. The secret is never printed. - Open storage buckets, database functions and the live postgres_changes feed
- storage
- RPC
- realtime
The places Row Level Security is most often forgotten: list and download files, call RPCs, subscribe to row changes with the public key. - IDOR, SQL injection and unsigned JWTs on the app's own API
- IDOR
- SQLi
- alg=none
Read another user's object, put a quote in id-like parameters, replay a token with the signature stripped. Admin-shaped routes and AI endpoints that spend credits are on the same pass. - Walk around the CDN to the origin, then greet the ports that should never be public
- 5432
- 6379
- 2375
- 2379
One connection each: Postgres 5432–5436, MySQL 3306, MongoDB 27017, Redis 6379, Elasticsearch 9200, CouchDB 5984, Memcached 11211, Docker 2375, etcd 2379, plus 3000, 8080, 15672 and the usual admin consoles. An address that does not serve this app is never probed further. No password is sent. - Enumerate accounts, skip the sign-in gate, open unlimited throwaway sign-ups
- enum
- path bypass
Different answers for a real vs fake email. Path variants that the matcher and the router normalize differently. Instant accounts with no CAPTCHA and no email check. If Clerk is present, an open sign-up is tried first. - Check whether the 2 secret keys in the public code work
- 25 detectors
A free, read-only call such as listing models. Then the steps to rotate them. - Download what should never be public: source maps, .env, .git, debug endpoints
- .env
- .git
- /metrics
Original TypeScript, environment files, the git folder, Spring actuator, Laravel Telescope, phpinfo, /metrics, /api/env. First bytes only; contents are not stored.
This preview sent nothing to your backend. It names the angles, not the holes: only the attack proves what works.