Hacking Enterprise Workspaces: Infiltrating Private Organizations with Just a Domain Name
One year ago, while testing an enterprise platform, I discovered an authorization vulnerability in their GraphQL API. The flaw allowed an attacker to enumerate private organizations, bypass access approvals, and join arbitrary enterprise workspaces using nothing more than a company’s email domain..

While testing a web application that uses GraphQL API, I uncovered an authorization flaw that allowed unauthorized users to enumerate private organizations and join them without approval or domain verification.
Background
The application in question allows teams and organizations to collaborate within workspaces. Users can be invited to organizations, and permissions determine what each user can access. so, ideally, no outsider should be able to read or modify internal data.
However, an oversight in how enterprise onboarding features were implemented exposed a direct path to cross-tenant access.
The Discovery
I started by checking whether GraphQL introspection was enabled. Although schema introspection was disabled, the API returned descriptive error suggestions when an operation or field name was close to an existing schema entity.
To map the attack surface further, I pulled the application’s client-side JavaScript bundles and searched for GraphQL queries and mutations. While many matched standard UI features, two operations stood out:
GetPublicOrganizationsByEmailDomain(Query)joinOrganizationByEmailDomain(Mutation)
Neither operation appeared anywhere in my standard dashboard. Looking deeper into the client logic revealed why: these endpoints belonged to an enterprise feature designed for Business-tier workspaces.
How the Feature Was Intended to Work
Admins on the Business tier could configure domain-based onboarding rules (e.g., automatically allowing any user with an @targetcompany.com email address to discover and join their workspace, or requiring admin sign-off).
During account registration, the frontend checked the user’s email domain:
- Common public email providers (such as Gmail, Yahoo, or Outlook) were excluded.
- For custom corporate domains, the client invoked
GetPublicOrganizationsByEmailDomain. - If matching organizations were found, the UI displayed their names and member previews, offering options to request access or join immediately.
- If the workspace allowed auto-joining, the client dispatched
joinOrganizationByEmailDomainwith the targetorganizationId.
The critical vulnerability was architectural: the backend relied on client-side routing rather than validating domain ownership server-side.
Leaking Organization IDs
First, the following GraphQL query could be sent with nothing more than a company’s email domain:
[
{
"operationName": "GetPublicOrganizationsByEmailDomain",
"variables": {"emailDomain": "targetcompany.com"},
"query": "query GetPublicOrganizationsByEmailDomain($emailDomain: String!)
{ publicOrganizationsByEmailDomain(emailDomain: $emailDomain)
{ _id members { user { email } } name } }"
}
]
The API returned matching organizations along with their internal _id, organization name, and the email addresses of existing members.
This alone constituted an information disclosure issue, enabling internal structure reconnaissance and employee email harvesting across any company on the platform.
Joining Any Organization
Next, I tried the joinOrganizationByEmailDomain mutation:
[
{
"operationName": "joinOrganizationByEmailDomain",
"variables": {"organizationId": "<OrganizationID>"},
"query": "mutation joinOrganizationByEmailDomain($organizationId: ID!)
{ joinOrganizationByEmailDomain(organizationId: $organizationId)
{ _id __typename } }"
}
]
The server accepted the request without validating whether the active session owned an email address matching the organization’s allowed domain.
The mutation executed successfully, immediately attaching my test account to the target workspace without requiring administrative approval.
Data Exfiltration
Once inside the target organization, access control checks evaluated my account as an active workspace member. This granted access to internal files, project assets, and proprietary documentation.
This vulnerability became significantly more critical when chained with a separate issue I had identified earlier: a feature permitting workspace data export to an external tenant. By chaining the two bugs, an attacker could:
- Target any organization by domain name.
- Enumerate its internal identifier and member directory.
- Force-join the organization via joinOrganizationByEmailDomain.
- Clone and export internal assets to an attacker-controlled workspace.
The Impact
With a single unauthenticated query, I could:
- Enumerate company members and structure
- Join any private organization
- Access and export confidential data
Root Cause
This vulnerability stemmed from two core flaws:
- Missing Server-Side Authorization: — The backend assumed that hidden UI elements equated to protected endpoints. The server failed to verify that the requesting session actually possessed a verified email matching the target domain before executing
GetPublicOrganizationsByEmailDomain. - Excessive Data Exposure: —
joinOrganizationByEmailDomainexposed sensitive organizational IDs and member directories before establishing authentication context or authorization to view that tenant.
Recommendations
To secure the workflow, the following controls were recommended:
- Enforce Strict Server-Side Domain Verification: Never trust client-provided parameters. Verify that the user’s authenticated session holds a confirmed email matching the domain whitelist before executing auto-join actions.
- Require Workspace Approval Tokens: Sensitive join actions should require signed invite tokens or explicit administrator confirmation rather than bare IDs.
- Minimize Public Data Exposure: Remove sensitive fields (such as internal member emails and database identifiers) from pre-auth or public queries.
- Audit Obfuscated Operations: Ensure all GraphQL types and resolvers implement uniform role-based access control (RBAC), regardless of whether they are exposed in general UI tiers.