Hey there!๐
Life has taught me one important lesson: "Disabled" rarely means disabled. It usually means hidden. And hidden things have a bad habit of leaking secrets.
This is the story of a feature that was supposedly turned off, a backend that never got the message, and how a greyed-out button quietly led to one of my highest-impact findings.
๐ง It Started Like Any Normal Recon Day
Nothing fancy. No zero-days. Just mass recon, half-empty coffee, and that familiar itch to poke things that look a little too clean.
The application was modern. React frontend. Clean UI. Lots of toggles and "Coming Soon" labels. One feature in particular caught my eye โ Advanced Reports.
The button was disabled. Greyed out. Tooltip said something like "This feature will be available soon."
Most users would stop there.
Bug bounty hunters don't.
๐ต๏ธ Watching the App Talk Too Much
Instead of clicking around, I opened DevTools and watched the network traffic while the page loaded.
Even though the feature was "disabled," the frontend was still making calls like:
GET /api/v2/feature-flags
GET /api/v2/user/permissions
GET /api/v2/reports/configThat was my first red flag.
If the backend is still sending feature configs, it usually means the logic exists. The UI is just pretending it doesn't.
And pretending is not security.
๐จ The Moment Things Feltโฆ Wrong
I noticed a request related to exporting reports:
POST /api/v2/reports/exportThe frontend only used it for basic exports. The payload looked harmless:
{
"type": "basic",
"format": "csv"
}Out of curiosity (and bad intentions), I changed one word.
{
"type": "advanced",
"format": "json",
"include": ["users", "roles", "audit_logs"]
}I hit send.
No error. No access denied. No "feature disabled" message.
Just a 200 OK and a download prompt.
That's when I stopped smiling.
๐ฃ What Came Back Wasn't "Coming Soon"
The exported file contained things I absolutely should not have had access to:
- User email addresses
- Internal role mapping
- Permission flags
- Audit metadata
- Feature toggles meant for enterprise tenants
This wasn't a broken UI bug. This was a backend authorization failure hiding behind a disabled button.
The frontend said no. The backend said "sure, why not."

๐งฉ The Real Issue (And Why This Happens So Often)
The root cause was painfully familiar:
- Feature flags enforced only in the frontend
- Backend trusted whatever the client sent
- No server-side entitlement validation
Someone assumed users wouldn't call endpoints that the UI doesn't expose.
That assumption pays bug bounty hunters very well.
๐ Digging Deeper: Backend / Frontend Mismatch
Once I confirmed the backend didn't care about feature access, I started testing parameters the frontend never touched.
For example:
Frontend request:
GET /api/v2/reports/list?limit=10Backend also accepted:
GET /api/v2/reports/list?limit=10&scope=globalNo role check. No tenant validation.
scope=user returned my data.
scope=global returned everyone's.
At this point, the impact was already high. But the app had one more mistake waiting for me.
๐ง When Cache Poisoning Joined the Party
The reports endpoint was behind a CDN.
I checked the headers:
Cache-Control: public, max-age=600
Vary: X-Feature-FlagThat made my stomach drop.
Why?
Because the backend trusted client-controlled headers to decide feature behavior.
So I tried this:
X-Feature-Flag: advanced_reports=trueThen requested:
GET /api/v2/reports/list?scope=globalThe response โ full of sensitive data โ was cached.
Meaning other users could now receive poisoned responses they were never supposed to see.
That's when this turned from "nice logic bug" into a serious cross-user data exposure via web cache poisoning.
๐งช Clean Proof of Concept (Realistic Flow)
1๏ธโฃ Identify disabled feature in UI Look for:
- Greyed-out buttons
- "Coming soon" labels
- Feature toggles in JS files
2๏ธโฃ Extract backend endpoints
grep -R "/api/" build/Or just watch XHR requests in DevTools.
3๏ธโฃ Replay the request manually
curl -X POST https://target.com/api/v2/reports/export \
-H "Authorization: Bearer <USER_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"type":"advanced",
"include":["users","roles","audit_logs"]
}'4๏ธโฃ Poison the cache
curl https://target.com/api/v2/reports/list?scope=global \
-H "X-Feature-Flag: advanced_reports=true"๐ Impact Summary (Why This Paid Well ๐ฐ)
- Feature flag bypass
- Backend authorization failure
- Access to enterprise-only data
- Web cache poisoning
- Cross-user sensitive data exposure
No fancy exploit chains. Just logic, patience, and a backend that trusted the UI too much.
Connect with Me!
- Instagram: @rev_shinchan
- Gmail: rev30102001@gmail.com
#EnnamPolVazhlkai๐