IOnclad  /  Features  /  Framework Safety
Risk Breakdown · Frameworks High

Every framework hands you a loaded footgun by default.

Django ships with DEBUG = True. Next.js will happily bundle a secret into the browser if you prefix it wrong. Supabase creates tables that anyone can read until you turn on row-level security. None of this is a bug in the framework. It's the default behavior doing exactly what it says, in a place you didn't mean for it to run. IOnclad knows the footgun for each stack and checks whether you pulled the trigger.

What counts as a framework footgun

A footgun is a security feature that exists, is documented, and is simply not turned on (or is turned off in the wrong environment). The framework gives you the safe path. The default, or a fast copy-paste, takes the unsafe one. IOnclad detects the stack from your files, then runs the checks specific to it:

Django DEBUG, ALLOWED_HOSTS, SECRET_KEY Next.js NEXT_PUBLIC_ leaks Express helmet, limiter, sessions React dangerouslySetInnerHTML Vue v-html Supabase missing RLS Flask debug, weak secret Rails CSRF, force_ssl Laravel APP_DEBUG Webhooks signature checks

Why these are dangerous

Each of these is a single line or a single missing line, and each one quietly hands an attacker something they shouldn't have.

1. DEBUG in production leaks your internals

DEBUG = True in Django (or debug=True in Flask, or APP_DEBUG=true in a Laravel .env) turns every error page into a full disclosure: stack traces, SQL queries, settings, sometimes environment variables. Flask's debugger goes further and lets a visitor run arbitrary Python from the browser. It's the fastest way to hand a stranger a map of your whole app.

2. The NEXT_PUBLIC_ prefix ships secrets to the browser

Any env var named NEXT_PUBLIC_, VITE_, REACT_APP_, or EXPO_PUBLIC_ gets inlined into the client bundle. That's by design for things like a Supabase anon key or a Stripe publishable key. But name it NEXT_PUBLIC_STRIPE_SECRET_KEY and your live secret is now in JavaScript that every visitor downloads. View source, find key, done.

3. No row-level security means the anon key owns your data

On Supabase, a Postgres table without RLS is readable and writable by anyone holding the anon key. The anon key is public by design and ships in your client bundle. So "create table, build the UI, launch" with no policy in between is a table the whole internet can dump and edit. This is the canonical day-one breach for vibe-coded apps.

4. Missing XSS and CSRF guards open the front door

React's dangerouslySetInnerHTML (and Vue's v-html) render raw HTML. Feed them user input without sanitizing and you have stored XSS. On the server, an Express app with no rate limiting lets attackers brute-force logins; a Rails app with protect_from_forgery except: leaves some state-changing actions open to CSRF. These are the defaults the framework gives you a way out of, if you take it.

The nastiest trap

A Supabase table with no RLS is not a "later" problem. The moment your anon key is in a shipped bundle (which is its whole job), every row in that table is public read and public write. There is no auth in front of it. Turn on RLS and write a policy before the table holds anything real.

The shape of a real incident

The Next.js version is almost a joke because it's so easy to do:

# .env.local, "I'll just expose it to the client real quick"
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_51H...redacted...4242
# works in dev, ships to prod, lives in the JS bundle forever

# the fix is one prefix:
STRIPE_SECRET_KEY=sk_live_51H...   # server-only, read via process.env in an API route

# and the Supabase version, same energy:
create table profiles (id uuid, email text, ssn text);  -- no RLS, anon key can read every row
alter table profiles enable row level security;          -- + a policy that scopes rows to auth.uid()
How IOnclad catches it

IOnclad has a dedicated framework scanner with 60+ per-stack checks. It first detects which frameworks are in your project, then runs only the checks that apply, all 100% offline:

IOnclad finds known patterns and common misconfigurations. It's not a pentest and not a guarantee, but these are exactly the defaults that ship broken.

How to fix it

Find every secret before someone else does.

Scan your code and full git history in under a minute. Free verdict, no signup, nothing leaves your machine.