All posts

March 14, 2026 · 4 min read

The QR Code on the Wall Pointed Straight at an API Nobody Meant to Make Public

I helped a small organization put together a check-in system for a recurring event last year: a tablet at the door running a simple web page, attendees scan a QR code, confirm their name, done. Straightforward, built quickly, worked well for months. The problem wasn't in the feature itself. It was in what the QR code made trivially discoverable to anyone who scanned it out of curiosity.

What the QR code actually pointed to

The QR code linked to the check-in page, which was fine on its own. But like most modern web pages, that page's real work happened through API calls visible in the browser's network traffic the moment it loaded, the same kind of thing I've written about checking on your own apps before. Someone at the event, apparently just poking around out of curiosity after scanning it, opened their phone's browser dev tools and found the underlying API call the check-in page made to look up a name.

What that API call revealed

The lookup endpoint took a partial name as a query and returned matching attendees. It had been built to only return the current event's list, which was the right instinct, but it had no rate limit and no check on how the request was being made, which meant it could be called directly, repeatedly, and quickly, outside of the check-in page's own interface entirely. Someone could pull the entire attendee list for the event, one query at a time, automated, in a few minutes, just by knowing the endpoint's shape, which a QR code handed them for free.

Why a QR code changes the risk calculation

A hidden or hard-to-find URL at least requires some effort to discover. A QR code posted publicly, on a wall, at an event, actively invites anyone physically present to scan it and land directly on the page, network requests and all. It's a convenience feature that also functions as a very direct advertisement of exactly where your app's API lives, to anyone who happens to be curious enough to look past the page itself.

What actually got fixed

  • The lookup endpoint got a rate limit, closing off the ability to pull the full list quickly regardless of who was calling it.
  • The response got trimmed to return only what the check-in page actually needed to display, not full attendee records with any extra fields that happened to come along for convenience.
  • The endpoint got scoped more tightly to the specific event and time window it was meant to serve, rather than staying reachable indefinitely after the event ended.

Nothing about this was a sophisticated attack. It was someone curious with a phone, doing exactly what I'd tell anyone to try on their own app: open dev tools, watch the network tab, see what's actually being asked for and handed back. The only difference here is that a QR code did the first step, pointing someone at the page, for free, to anyone standing nearby.

Related reading

Harbova is a security service for apps built with AI tools. Start with a free scan, and if it finds something serious, we can fix it and prove it is closed.