Tenant isolation
Description
Uses the rules defined by the users to detect same object instances detected by two different users whereas this is prohibited. According to the rules provided in the configuration file, the same instance or object can be detected by two different users which is prohibited.
Remediation
When accessing the application via GraphQL, we must validate whether or not the user has access to the requested elements from the schema. Especially we must implement access control policies on every path of the Graph leading considered field or object.
The authorization logic belongs to the business logic layer, and from there it is accessed by GraphQL. This way, the application can have a single source of truth for authorization, which can then be used for other access points.
Among the several access control policies we can implement in our application, the two most popular ones are Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC). - With Role-Based Access Control, we grant permissions based on roles, and then assign the roles to the users. For instance, WordPress has an administrator
role with access to all resources, and the editor
, author
, contributor
, and subscriber
roles, which each restrict permissions in varying degrees, such as being able to create and publish a blog post, just create it, or just read it. - With Attribute-Based Access Control, permissions are granted based on metadata that can be assigned to different entities, including users, assets, and environment conditions (such as the time of the day or the visitor's IP address). For instance, in WordPress, the capability edit_others_posts
is used to validate whether the user can edit other users' posts.
In general terms, ABAC is preferable over RBAC because it allows us to configure permissions with fine-grained control, and the permission is unequivocal in its objective.
GraphQL Specific
Apollo
Ensure that the Apollo framework engine is configured to provide tenant isolation by implementing separate data stores for each tenant, using authentication and authorization mechanisms to control access, and applying schema validation to prevent data leaks between tenants.
Yoga
Ensure that the Yoga framework engine is configured to enforce strict tenant isolation. This can be achieved by implementing unique execution contexts for each tenant, such as separate database schemas, dedicated service instances, or isolated runtime environments. Additionally, apply rigorous access controls and authentication mechanisms to prevent cross-tenant data access or resource interference.
Awsappsync
Ensure that AWS AppSync resolvers are configured to enforce tenant isolation by using context-based dynamic resolution. This can be achieved by incorporating tenant identifiers into the resolver logic, which ensures that data is only accessible to the appropriate tenant. Additionally, utilize AWS Identity and Access Management (IAM) policies to control access at the API level, and consider implementing field-level authorization for fine-grained access control.
Graphqlgo
Implement strict tenant isolation mechanisms within the GraphQL Go framework by enforcing access controls and segregating query execution contexts per tenant. Utilize middleware to validate tenant IDs and ensure that data queries and mutations are scoped exclusively to the authenticated tenant's data set. Regularly audit and test isolation features to prevent cross-tenant data leaks.
Graphqlruby
In the GraphQL Ruby framework, ensure tenant isolation by implementing a context-based authorization mechanism. This can be achieved by using the context object to store the current user's information and then applying scope filters to resolve functions. This ensures that users can only access data that belongs to their tenant. Additionally, consider using the pundit or cancancan gems for more granular permission controls.
Hasura
Ensure that the Hasura GraphQL engine is configured to use role-based access control (RBAC) to enforce tenant isolation. Define roles corresponding to different tenants and set permissions for each role to restrict access to data that belongs to that tenant only. Use session variables to dynamically apply the appropriate role for each request based on the authenticated user's tenant.
REST Specific
Asp_net
Implement strict tenant isolation by enforcing access controls and ensuring that each user's data is stored and processed in a separate context. Utilize ASP.NET's built-in features such as custom authorization filters, resource-based authorization, or multi-tenancy frameworks to prevent cross-tenant data access.
Ruby_on_rails
Implement scoped queries within the Rails application to ensure that users can only access objects within their own tenant. Use ActiveRecord's default_scope
or explicit scoping methods to filter records based on the tenant's ID associated with the current user. Additionally, apply strong parameter validation and access control checks before any object instantiation or data processing to prevent unauthorized cross-tenant data access.
Next_js
Implement strict access controls and logical separation of tenant data. Utilize middleware to enforce tenant isolation policies and ensure that database queries are scoped to the authenticated user's tenant context.
Laravel
Implement middleware to enforce tenant isolation by validating the user's access rights to the requested resource, ensuring that each user can only access data within their own tenant scope.
Express_js
Implement middleware in Express.js to enforce tenant isolation by validating the user's session and ensuring that each user can only access their own tenant's data. Use scoped queries based on user context and avoid direct object references from user input.
Django
Implement strict tenant isolation by using Django's built-in support for database schemas and ensuring that querysets are properly scoped to the current user's tenant. Apply middleware to enforce tenant context and use Django's permissions framework to control access. Regularly audit code to prevent cross-tenant data leaks.
Symfony
Implement access control checks within the Symfony framework to ensure that each user can only access or modify objects that they are authorized to. Use Symfony's security components, such as Voters or Access Decision Managers, to enforce strict permissions on a per-object basis. Additionally, ensure that user sessions are properly isolated and that any API endpoints or controllers that handle object retrieval or manipulation include proper authentication and authorization checks.
Spring_boot
Implement multi-tenancy with separate schemas or databases for each tenant to ensure complete isolation. Use Spring Security to enforce authentication and authorization rules, and apply method-level security to prevent cross-tenant data access. Additionally, configure Spring Data JPA or Hibernate filters to automatically apply tenant context to all database queries.
Flask
Implement strict access control checks based on user sessions and roles to ensure that each tenant can only access their own data. Use Flask's session management and decorators to enforce these controls.
Nuxt
Implement strict access control checks based on user roles and permissions to ensure that each tenant can only access their own data. Use middleware to validate the user's session and enforce tenant isolation at the API level within the Nuxt.js application.
Fastapi
Implement role-based access control (RBAC) and scope-based authorization to ensure that users can only access objects within their permitted areas. Use FastAPI's dependency injection system to create security dependencies that verify the user's role and scope before granting access to any object instance. Additionally, ensure that all database queries are properly scoped to the user's context to prevent cross-tenant data access.
Configuration
Identifier:
access_control/tenant_isolation
Parameters
objects : A list of private objectNames
. A single instance of this object should not be access by 2 different users. Each object instance is identified by its ID.
scalars : A list of scalar fieldName
. A specific scalarValue
of this field should not be access by 2 different users. Each scalar instance is indentified by its value.
paths : List of the paths of the routes to control, compliant with the OpenAPI route format. See https://swagger.io/docs/specification/paths-and-operations/.
Examples
GraphQL: Accessiblity of objects private instances for differents users
{
... Authentication settings ...
... Other configuration settings ...
"checks": {
... Other checks ...
"access_control/tenant_isolation": {
"parameters": {
"objects": [
"MyVeryPrivateData", # Record access to object `MyVeryPrivateData`
# if two different users access the same object
# (i.e. two different users access the same self bound private data)
# the an alert will be raised.
],
"scalars": {
"Post": [
"createdBy", # Record access to field `createdBy` of object `Post`
# if two different users can access the same scalar value
# an alert will be raised.
]
}
}
}
... Other checks ...
}
... Other configuration settings ...
}
REST: Enforce tenant isolation on path /users/{id} and /me
{
... Authentication settings ...
... Other configuration settings ...
"checks": {
... Other checks ...
"access_control/tenant_isolation": {
"parameters": {
"paths": [
"/users/{id}",
"/me"
]
}
}
... Other checks ...
}
... Other configuration settings ...
}
Ignore this check
checks:
access_control/tenant_isolation:
skip: true
Score
- Escape Severity: HIGH
Compliance
OWASP: API5:2023
pci: 7.1.2
gdpr: Article-25
soc2: CC6
psd2: Article-95
iso27001: A.18.1
nist: SP800-53
fedramp: AC-4
Classification
- CWE: 264
Score
- CVSS_VECTOR: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C
- CVSS_SCORE: 7.2