← Back to Wiki
Security / Access Control

A Vishing Attempt Turned Up a Real UniFi RBAC Bug

A social-engineering attempt that didn't work is still a good reason to go audit everything else. A precautionary sweep across a home network's infrastructure — triggered by an unrelated vishing call — turned up an automation API key with far more access than it needed, and a role downgrade that looked like a fix but wasn't a complete one.

Share on X

Why an unrelated phone call led to auditing a router

The call itself never got anywhere — it targeted a Google account, not any self-hosted infrastructure. But a caller who's done real reconnaissance is worth taking seriously as a signal, not just a one-off. The reasonable response isn't "nothing happened, move on" — it's a precautionary pass across everything that account, or an account like it, could plausibly be used to pivot toward: source control, password managers, cloud accounts, and the network controller itself.

What the audit found

Buried in that sweep: a UniFi Network API key, created months earlier for a read-only documentation-sync job, was backed by an admin account still set to Super Admin. Nothing had ever actually needed that level of access — the automation only ever listed sites, devices, and clients. It had just never been revisited since the day it was created.

The obvious fix: drop that account down to a restricted role. UniFi supports exactly this — a custom viewer role, with both the network and admin permission scopes set to "View Only", already existed and was in use by a separate, correctly-scoped automation account on the same controller. Applying the same role to the over-privileged key looked like a clean, complete fix.

The part that didn't actually get fixed

The role change didn't close the real gap. UniFi's granular admin roles (Super Admin vs. Viewer, with separate Network/Admin permission scopes) govern the modern Integrations API and most of the Network app's own UI. They do not appear to govern a legacy endpoint — GET /proxy/network/api/s/<site>/rest/account — which still returned full account records, including a plaintext password field, from a key backed by an account explicitly downgraded to view-only. Same request, same response, before and after the role change.

This was confirmed directly: the same API key, using the same credential, hit that endpoint before and after the role downgrade and got byte-for-byte the same sensitive fields back both times. If your only verification step is "I changed the role, so it's fixed," you can walk away from an incident like this with a false sense of closure.

What to actually do about it

Report platform gaps like this upstream. A permission model that silently doesn't apply to one endpoint is a real bug, not a configuration mistake — worth filing with the vendor so it gets fixed for everyone, not just worked around locally.