How to Test Multi-Tenant Authorization Vulnerabilities with Strix Security Scanner

How to Test Multi-Tenant Authorization Vulnerabilities with Strix Security Scanner

Multi-tenant SaaS applications are a prime target for authorization vulnerabilities. If tenant isolation fails, one customer can access another customer's data—a critical flaw that regulators, auditors, and security teams take extremely seriously. This guide walks you through detecting these vulnerabilities before they become a compliance nightmare.

The Multi-Tenant Authorization Problem

Multi-tenant applications share infrastructure while isolating customer data. However, many developers implement authorization checks that are incomplete. A customer with ID tenant_123 might be able to:

  • Access resources belonging to tenant_456 by manipulating query parameters
  • Call APIs intended for other users within their own tenant
  • Exploit role-based access control (RBAC) gaps between tenants

In 2025, a major DoD-backed contractor was discovered with zero tenant isolation in their authorization layer. A researcher using automated security scanning found that API endpoints returned data for any tenant ID, regardless of the authenticated user's actual tenant. This exposed military training data and required a five-month responsible disclosure process.

Why Automated Testing Matters

Manual code review alone misses authorization flaws because:

  1. Implicit assumptions: Developers assume frameworks handle tenant isolation (they don't automatically)
  2. Edge cases in permission logic: Complex role hierarchies create blind spots
  3. Data exposure at scale: With thousands of endpoints, manual testing is incomplete
  4. False negatives from integration testing: Your QA environment may not properly simulate multi-tenant scenarios

Automated security scanners like Strix test authorization by attempting cross-tenant access patterns at scale.

Setting Up Strix for Authorization Testing

Step 1: Install and Configure Strix

# Install Strix CLI
npm install -g @strix/security-cli

# Initialize Strix in your project
strix init --auth bearer

# Configure your API base URL
strix config set api-url https://api.yourdomain.com

Step 2: Define Your Multi-Tenant Authentication

Create a .strix/auth.config.js file to teach Strix how to authenticate as different tenants:

module.exports = {
  authType: 'bearer',
  getToken: async (tenantId, userId) => {
    const response = await fetch('https://api.yourdomain.com/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: `user+${tenantId}@test.com`,
        password: process.env.TEST_PASSWORD
      })
    });
    const { token } = await response.json();
    return token;
  },
  tenants: [
    { id: 'tenant_001', name: 'Customer A' },
    { id: 'tenant_002', name: 'Customer B' },
    { id: 'tenant_003', name: 'Customer C' }
  ]
};

Step 3: Create an OpenAPI Spec for Your API

Strix needs to know which endpoints to test. Generate or write an OpenAPI 3.0 specification:

openapi: 3.0.0
info:
  title: Multi-Tenant API
  version: 1.0.0
paths:
  /api/documents/{documentId}:
    get:
      operationId: getDocument
      parameters:
        - name: documentId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Document retrieved
  /api/users/{userId}/profile:
    get:
      operationId: getUserProfile
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: User profile

Step 4: Run Cross-Tenant Authorization Tests

# Run Strix authorization scanner
strix scan --auth-config .strix/auth.config.js --openapi api.yaml --test-type tenant-isolation

# Output includes vulnerability report:
# [CRITICAL] GET /api/documents/{documentId}
# Tenant A can access Tenant B's documents
# Evidence: Status 200, returned data for tenant_002 when authenticated as tenant_001

Understanding Strix's Tenant Isolation Test Matrix

| Test Scenario | What It Tests | Example | |---|---|---| | Direct Cross-Tenant Access | Can user from tenant A access tenant B's resources by ID? | GET /api/documents/doc_from_tenant_b | | Parameter Manipulation | Can attacker change tenant_id in query params or headers? | GET /api/docs?tenant_id=attacker_tenant | | Role Escalation Between Tenants | Can a guest user in tenant A become admin in tenant B? | POST /api/roles with escalated permissions | | Hidden Data Exposure | Do error messages leak existence of other tenants' data? | 401 vs 404 responses revealing tenant IDs | | Implicit Tenant Context | Is tenant derived only from auth token, not user input? | Check Authorization header is the single source of truth |

Interpreting Scan Results

Strix outputs findings in three severity levels for authorization:

CRITICAL: Zero Tenant Isolation

Vulnerability: Zero Tenant Isolation
Endpoint: GET /api/training-modules/{moduleId}
Finding: Any authenticated user can access any moduleId regardless of tenant
Proof:
  - Authenticated as tenant_001_user
  - Requested GET /api/training-modules/module_from_tenant_002
  - Received 200 OK with full module data
Fix: Add tenant check in handler:
  if (requestingUser.tenantId !== resource.tenantId) {
    throw new ForbiddenError('Unauthorized')
  }

HIGH: Tenant ID User-Controlled

Vulnerability: Tenant Determined by User Input
Endpoint: POST /api/invoices
Finding: tenantId taken from request body instead of auth token
Proof:
  - Authenticated as tenant_001_user
  - POST body: {"tenantId": "tenant_002", "amount": 5000}
  - Invoice created for tenant_002
Fix: Extract tenant from JWT:
  const tenantId = req.user.tenantId; // from token
  // DO NOT use req.body.tenantId

MEDIUM: Overpermissive Error Messages

Vulnerability: Information Disclosure via Error Messages
Endpoint: GET /api/users/{userId}
Finding: 401 when user not found vs 404 when user is from different tenant
Impact: Attacker can enumerate valid user IDs across tenants

Integrating into Your CI/CD Pipeline

Add Strix authorization scanning to your GitHub Actions workflow:

name: Security Scan
on: [push, pull_request]
jobs:
  strix-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Strix Authorization Tests
        run: |
          npm install -g @strix/security-cli
          strix scan \
            --auth-config .strix/auth.config.js \
            --openapi api.yaml \
            --test-type tenant-isolation \
            --fail-on critical
      - name: Upload Results
        uses: strix-ai/results-action@v1
        if: always()
        with:
          results-file: strix-report.json

Best Practices for Multi-Tenant Authorization

  1. Derive tenant from token, never from user input: Extract tenantId from JWT claims, not request parameters
  2. Fail open on missing tenant checks: Default deny access if tenant cannot be determined
  3. Test every endpoint: Even admin endpoints need tenant isolation verification
  4. Version your authorization logic: Document RBAC rules in your OpenAPI spec
  5. Use responsible disclosure timelines: Like the DoD contractor case, give security researchers 90-180 days to disclose issues

Common False Positives and How to Avoid Them

Public Endpoints: Strix may flag shared resources as tenant isolation issues. Mark them in your OpenAPI spec:

security: []
responses:
  '200':
    description: Public resource (no tenant isolation required)

Rate Limiting: Cross-tenant tests trigger rate limits. Configure Strix with proper delays:

strix scan --rate-limit 100ms --retry-count 3

Conclusion

Multi-tenant authorization vulnerabilities are difficult to find manually but trivial to detect with automated testing. Running Strix's authorization scanner as part of your release process prevents the kind of zero-isolation bugs that exposed military data and triggered mandatory disclosure requirements.

Start with your most sensitive endpoints (user profiles, financial data, training modules) and expand from there. The cost of catching these bugs before production is infinitesimal compared to the regulatory and reputational fallout.

Recommended Tools

  • SupabaseOpen source Firebase alternative with Postgres