July 15, 2026
I Just Wanted a Cold Coffee. Instead I Found a Master Key to a Vending Machine Empire.
A cautionary tale about snacks, curiosity, and why you should never F12 near a vending machine.

By Gokul
4 min read
The Crime Scene: A Vending Machine, 6 PM, Mild Hunger
Picture it. It's evening. I'm standing in front of one of those smart, WiFi-connected, "scan-to-pay" vending machines — the kind that make you feel like you're living in the future, right up until you realize the future runs on a JavaScript bundle with the security posture of a screen door.
I wasn't hunting bugs. I wanted a cold coffee. That's it. That was the entire mission brief.
But old habits die hard, and "old habits" for a pentester means popping open DevTools the way normal people check their phone at a red light. Purely out of muscle memory, I peeked at the network tab while the app loaded.
And there it was. Sitting in the main JS bundle, in plain text, like it had nowhere better to be: an authHeader value. A hardcoded bearer token. Not a session token. Not a temp token. A master credential, chilling in a production JavaScript file, doing absolutely nothing to justify why it should be trusted with anything.
My cold coffee would have to wait.
Evidence — the config object, main.[hash].js:
"authHeader": "Bearer MG5hY3RhOD...[REDACTED]...MEs4Tkc4UTFVS2s9""authHeader": "Bearer MG5hY3RhOD...[REDACTED]...MEs4Tkc4UTFVS2s9"CVSS 9.8. CWE-798 (Use of Hardcoded Credentials). A static, master-level bearer token, shipped in a public production bundle, valid without OTP, without login, without so much as a "who goes there."
Rabbit Hole, Population: Me
Here's the thing about a hardcoded high-privilege token — it's less "vulnerability" and more "skeleton key that opens every door in the building, including the ones marked 'do not open.'" So naturally, I had to see what doors it opened.
Door #1: The Corporate Client List
Hitting the employer-facing endpoint with this token didn't return "access denied." It returned what I can only describe as a full B2B guest list — dozens of corporate partner records, complete with the internal email domains used to verify employees and their wallet balances. It read like a highlight reel of recognizable brands across gaming, finance, aviation, cybersecurity, and consumer tech. Great for reconnaissance if you're a threat actor planning a phishing campaign against someone's payroll team. Not great for literally anyone else.
Evidence — GET /kwik24/v2/employer:
{
"id": 61,
"company_name": "[REDACTED]",
"email_domain": "@[REDACTED].com",
"wallet_amount": 1500
},
{
"id": 68,
"company_name": "[REDACTED]",
"email_domain": "@[REDACTED].com",
"wallet_amount": 2500
}
// ...69 more records just like this{
"id": 61,
"company_name": "[REDACTED]",
"email_domain": "@[REDACTED].com",
"wallet_amount": 1500
},
{
"id": 68,
"company_name": "[REDACTED]",
"email_domain": "@[REDACTED].com",
"wallet_amount": 2500
}
// ...69 more records just like thisSeventy-one corporate records in one unauthenticated call. CVSS 9.1, CWE-284 (Broken Access Control / IDOR).
Door #2: The Vending Machine's Diary
Next stop, a settings endpoint that had zero business being reachable without auth. It happily coughed up the internal WiFi SSID and password for the machine's network, plus the internal IP address of the MQTT broker controlling the hardware. Translation: if you can stand next to the machine, you can join its private network and start talking to the thing that dispenses my cold coffee. That's not a vending machine anymore, that's an IoT device wearing a vending machine costume, and it has trust issues.
Evidence — GET /kwik24/v2/app/settings:
SSID: [REDACTED]
Password: [REDACTED]
MQTT Endpoint: tcp://[REDACTED]:1883
Secondary SSID: [REDACTED]_Free_Wifi
Test Location IDs: 40, 5545, 6460, 8992, 8846SSID: [REDACTED]
Password: [REDACTED]
MQTT Endpoint: tcp://[REDACTED]:1883
Secondary SSID: [REDACTED]_Free_Wifi
Test Location IDs: 40, 5545, 6460, 8992, 8846CVSS 8.2, CWE-200 (Information Exposure). An unauthenticated MQTT broker plus real WiFi creds means someone within Bluetooth-selfie-range of the machine could pivot onto its network.
Door #3: The Money
And finally, because why stop at "mildly terrifying," the same token unlocked a balance-check endpoint, which returned actual wallet credit — real money, sitting there, accessible to anyone who bothered to look.
Evidence — GET /kwik24/v2/payment/balance:
{
"balance_details": [
{
"balance": [REDACTED],
"type": "kwik24credit",
"registered": true
}
],
"kwik24CreditAvailable": [REDACTED]
}{
"balance_details": [
{
"balance": [REDACTED],
"type": "kwik24credit",
"registered": true
}
],
"kwik24CreditAvailable": [REDACTED]
}CVSS 7.7, CWE-284 (Broken Access Control). Four figures' worth of system credit, one curl command away.
So to recap: one hardcoded token, discovered while procrastinating a snack purchase, cascaded into corporate data exposure, internal network access, hardware-adjacent control, and a peek at real financial balances. Four findings, one JS file, zero effort. Honestly kind of insulting how easy it was.
The Responsible Part (I Promise I Have Some)
I did not, in fact, use this newfound god-mode to buy myself a lifetime supply of chips. I closed DevTools, took a breath, and did what any reasonably well-adjusted security researcher does: wrote it all up and reached out to the team to figure out the right channel for responsible disclosure.
The findings, roughly ranked by "how much this should not exist":
- Hardcoded master bearer token (Critical) — the origin of all sins
- Mass corporate partner data disclosure (Critical) — recon gold for phishing
- Infrastructure & WiFi credential exposure (High) — physical-world risk from a purely digital bug
- Unauthorized access to financial balances (High) — because apparently the theme was "everything, all at once"
The Reward: A Plot Twist Nobody Saw Coming
Here's my favorite part of this whole story. I went to buy a snack. I left with a critical vulnerability chain, a mild existential crisis about how many other vending machines are out there like this, and — once the report was triaged — a ₹10,000 wallet credit as a bug bounty reward.
So somewhere out there is a version of events where I paid for a cold coffee using money I got from finding out I could've stolen unlimited cold coffees for free. The universe has a sense of humor, and apparently so does the security team, because they fixed it fast and didn't just laugh me out of the inbox.
The Actual Lesson (Yes, There's One)
Hardcoding a high-privilege token client-side is the security equivalent of writing your house key's shape on a sticky note and taping it to your front door "just in case." It doesn't matter how well-designed the rest of your access control is if the master key is sitting in a .js file anyone can Ctrl+F.
If your app's frontend needs to talk to something sensitive, that logic — and that credential — belongs server-side, behind proper authentication, not shipped to every browser that loads your page.
And if you're a curious pentester standing in front of a vending machine: yes, open DevTools. But maybe buy the snack first. Some things shouldn't wait.
Details in this post have been generalized and sensitive evidence (tokens, credentials, IPs, and the full partner list) has been redacted, in line with responsible disclosure practice. This vulnerability was reported through the appropriate channel and addressed by the vendor.