Advanced levelPremiumbounty: $3500

Client-side admin bypass — boolean manipulation + BAC in a modern SPA

Real Quora report: SPA with an isAdmin boolean in localStorage that controls the UI + a backend that doesn't validate server-side. How to chain a boolean flip with BAC for admin takeover.

Gorka El BochiMay 11, 202613 min

Quick answer

Modern SPAs (React, Vue, Svelte) receive flags like isAdmin: false from the server and use them to condition which UI to show. The bug: if the flags also determine whether admin actions are allowed to run server-side (instead of checking the real role from the JWT), it's enough to flip the boolean in the response to unlock the entire admin panel. Quora paid $3,500 (H1 #3567641) for exactly this — 30+ flags, UserAdminLogPaginationQuery executable with a normal session, full GraphQL admin map. The pattern appears in 80%+ of Series A/B SaaS admin panels.


1. The bug class: client-side enforcement

CWE-602 "Client-Side Enforcement of Server-Side Security". The vulnerable architecture:

arduino
[Server] ──"isAdmin: false"──→ [Client React]
                                       │
                                       ▼
                            if (isAdmin) <AdminPanel/>
                                       │
                                       ▼ user clicks button
                            POST /admin/delete-user
                                       │
                                       ▼
                          [Server] ✅ procesa sin chequear rol

The frontend gating is UX only. If the server doesn't re-validate the role before running actions, the attacker:

  1. Manipulates the response so the frontend renders the admin controls.
  2. Uses those controls to invoke the actions.
  3. The server runs them because it "believed" only the admin frontend could call them.

2. Detection — the 6-line script

When you reach a target and log in with a normal account, paste this into the DevTools Console:

javascript
// Detect client-side admin flags in initial state
const text = document.documentElement.innerHTML;
const matches = text.match(/"(is[A-Z]\w+|can[A-Z]\w+|enable\w+|allow\w+)":\s*(true|false)/g) || [];
const interesting = matches.filter(m => /admin|debug|internal|dev|super|test|moderat/i.test(m));
console.table(interesting.map(m => m.replace(/[":,\s]/g, " ").trim().split(" ")));

If the table has 5+ flags with admin/debug/internal/moderat in the name and all at false → vulnerable to this bypass with high probability. If it has 30+ → it's the report of the year.

Real-world output (Quora case 2026)

arduino
isAdminMode               false
isAdmin                   false
tribes_super_admin        false
isAdminLogTab             false
isDevCode                 false
isCanaryRevision          false
debugToolsEnabled         false
isMemberQuoraEmployee     false
EnableSubscriptionsDebugMode  false
... (30+ flags adicionales)

Keep reading the full chain

The remaining part includes the step-by-step PoC, exploitation code and the full chain that led to impact. Available to subscribers.

Practice this in a lab

Client Side Admin Bypass

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

hunters training
711

hunters training

labs from real reports
55

labs from real reports

completions
1,205

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy