The Sibling Service That Skipped Authentication
The main app enforces auth well, but a sibling service on the same estate does not. Here is why the side door stays unlocked and how to close it.
What this is
An unauthenticated sibling service is a second service, running on the same estate as a well-defended application, that enforces no authentication of its own. The main product does everything right - real login, sessions, a gateway that checks every request. Then a serverless function, a microservice, a background-job engine, or a model-server sits next to it on the same infrastructure, internet-reachable, asking nobody for a credential. The front door is locked and monitored. A side door on the same building stands open.
This is one of the most reliable findings we produce, because the security of the main app actively hides it. A team that has hardened its front door reasonably believes the building is secure. The sibling never got the same attention because it was never thought of as a door.
Why it keeps happening
Security review follows where the team expects attackers to arrive, and that is the user-facing app. The login flow gets threat-modeled. The gateway gets an auth filter. The session handling gets tested. All of that attention concentrates on the one surface everyone agrees is exposed.
The supporting services are built under a different mental model. A serverless function gets deployed to do one job and defaults to public because that was the quickest way to make it callable. A microservice gets mounted into the mesh but not behind the gateway’s auth filter, because it was “internal.” A GPU model-server or a job engine gets stood up beside the app to serve it, and the team assumes the app in front is the only caller. Each of these is a reasonable local decision. Together they produce a building with one guarded entrance and several unguarded ones.
The most common and most dangerous variant is the front-end assumption: the single-page app enforces login, so the team treats that login as the gate for the whole system. But the backend the front-end talks to is often directly reachable, and it runs with auth disabled because “the front-end already checks.” An attacker never touches the front-end. They call the backend directly, and the only lock in the system is the one they walked around.
How the attack works
Finding a sibling service is enumeration, not exploitation:
- Map the estate. Subdomains, API hosts, function URLs, and the network calls the front-end makes all point at services beyond the main app. Black-box, from outside, this surface is visible.
- Probe each one for its auth posture. Send a plain request to each service with no credential. The main app returns
401. Somewhere on the estate, a sibling returns200and does its job. - Call the sibling directly. Whatever that service does - process a payment, run a model, drive a maintenance action, return records - the attacker now does it without ever authenticating, because the only authentication in the system lived in a front-end they skipped.
There is no bypass and no clever payload. The attacker simply talks to the service that never asked them to log in.
What it looks like in the wild
We have found this across companies that share nothing but the shape of their infrastructure.
-
A cloud-telephony AI voice platform ran GPU model-server sidecars deployed without the authentication its main gateway enforced. The gateway was solid. The model-servers behind it, reachable on their own, were not. Full teardown: No Lock on the GPU.
-
A cardiac-telehealth clinic treated its single-page app’s login as the only gate. Its serverless billing functions were internet-reachable with no authentication of their own. The clinical data was locked; the billing side door was not, and it was directly callable. Full teardown: The Billing API With No Front Door.
-
An EV-charging network mounted an internal maintenance and utility router with its per-route authentication commented out. The customer-facing app was hardened; this administrative router, reachable on the same estate, ran the network’s operational actions for anyone who found it. Full teardown: The Maintenance API That Ran the Network.
-
An AI lending platform and a healthcare voice-AI company each ran backends with authentication disabled behind auth-enforcing front-ends. In both cases the front-end login was real, and in both cases it protected nothing an attacker had to go through, because the backend answered directly.
-
A commercial-lending platform ran an unauthenticated job engine on the same service mesh as its hardened application. The main app would have turned an attacker away. The job engine, one hop over, would not.
The consistent theme: the strength of the main app is exactly what keeps the sibling out of scope in everyone’s mind, right up until someone enumerates the estate instead of the app.
How to tell if you are exposed
A short self-check:
- Enumerate every internet-reachable service on your estate, not just the main app - subdomains, function URLs, microservice hosts, model-servers, job engines, admin and utility routers.
- Send each one a request with no credential. Anything that returns
200and does real work is an open door, regardless of how well the front door is locked. - For every backend your front-end talks to, ask whether it is directly reachable. If it is, test it without going through the front-end. If it answers, the front-end’s auth is protecting nothing.
- Read your gateway config for services mounted outside the auth filter, and your serverless functions for any set to public. Look specifically for authentication that was commented out or “temporarily” disabled.
How to fix it
- Enforce auth at the gateway for every service, deny by default. No service reaches the network without passing through authentication. A new service is unreachable until it is explicitly placed behind the gate, never reachable-until-secured.
- Inventory every internet-reachable service and its auth posture. You cannot protect what you have not listed. Maintain a live inventory of every service that answers from outside and whether it authenticates, and treat any unauthenticated entry as an incident.
- Never assume the front-end protects the backend. Treat “the front-end checks it” as no protection at all. Every backend authenticates its own callers, because an attacker will reach it directly.
- Give siblings the same review as the front door. Model-servers, job engines, billing functions, and maintenance routers are doors. Threat-model them the way you threat-model the login flow, because an attacker enumerates the estate, not the app.
The takeaway
Attackers do not attack your app; they attack your estate. A hardened front door counts for nothing if a serverless function, a model-server, or a maintenance router on the same infrastructure answers without a credential. Enumerate every service, deny by default, and treat “the front-end checks it” as no protection at all. See this pattern in the field in No Lock on the GPU and its siblings.
Frequently asked
What is an unauthenticated sibling service?
Why does the main app get secured but the sibling does not?
Does front-end authentication protect the backend?
This is one finding from a harness that runs continuously. See how Greywatch finds, proves, and fixes them.
How it works →



