Files
igny8/CRITICAL_SITE_ISOLATION_BUG_FIX.md
alorig 1a1214d93f 123
2025-11-22 13:07:18 +05:00

5.8 KiB

🚨 CRITICAL SITE ISOLATION BUG FIX

Issue Summary

Severity: CRITICAL
Date: November 22, 2025
Reporter: User
Status: FIXED

Problem Description

All sites in the application (sites 5, 10, 14, 15) were showing IDENTICAL integration settings and content types. This is a critical data isolation bug where:

  • Site 5 (homeg8.com) integration data was being shown for ALL sites
  • Sites 10, 14, and 15 were displaying the SAME content types and sync data as site 5
  • This violates fundamental data isolation principles and could lead to:
    • Data leakage between different sites
    • Incorrect content being synced to wrong sites
    • Security and privacy concerns

Root Cause Analysis

Backend Issue

In igny8/backend/igny8_core/api/base.py, the SiteSectorModelViewSet.get_queryset() method was checking for site_id query parameter:

site_id = query_params.get('site_id')  # Line 268

Frontend Issue

In igny8/frontend/src/services/integration.api.ts, the getSiteIntegrations() method was passing site (not site_id):

const response = await fetchAPI(`/v1/integration/integrations/?site=${siteId}`);  // Line 37

The Bug

Parameter Mismatch:

  • Frontend sends: ?site=5
  • Backend expects: ?site_id=5
  • Result: Backend IGNORES the site filter and returns ALL integrations for ALL sites!

This meant:

  1. When site 5 requests integrations, it gets ALL integrations
  2. When site 10 requests integrations, it gets ALL integrations
  3. When site 14 requests integrations, it gets ALL integrations
  4. Since they all return the first WordPress integration (integration ID 1), all sites display the SAME data

The Fix

File Modified

igny8/backend/igny8_core/api/base.py (Lines 261-272)

Change Made

Updated the query parameter check to accept BOTH site_id and site:

# OLD CODE (BROKEN):
site_id = query_params.get('site_id')

# NEW CODE (FIXED):
site_id = query_params.get('site_id') or query_params.get('site')

This ensures backwards compatibility and proper filtering regardless of which parameter is used.

Why This Fix Works

  1. Accepts both parameters: Now works with ?site=5 OR ?site_id=5
  2. Proper isolation: Each site now only sees its OWN integrations
  3. No breaking changes: Existing code using site_id continues to work
  4. Fixes the frontend: The existing frontend code now works correctly

Impact

Before Fix (BROKEN)

GET /api/v1/integration/integrations/?site=5
→ Returns ALL integrations (no filtering)
→ Site 5 sees integration ID 1 (homeg8.com)

GET /api/v1/integration/integrations/?site=10
→ Returns ALL integrations (no filtering)
→ Site 10 ALSO sees integration ID 1 (homeg8.com) ❌

After Fix (CORRECT)

GET /api/v1/integration/integrations/?site=5
→ Returns ONLY site 5's integrations
→ Site 5 sees its OWN integration

GET /api/v1/integration/integrations/?site=10
→ Returns ONLY site 10's integrations
→ Site 10 sees its OWN integration ✅

Testing Steps

  1. Verify site isolation:

    # Site 5
    curl "https://app.igny8.com/api/v1/integration/integrations/?site=5"
    # Should return ONLY site 5 integrations
    
    # Site 10
    curl "https://app.igny8.com/api/v1/integration/integrations/?site=10"
    # Should return ONLY site 10 integrations (different from site 5)
    
  2. Check content types:

  3. Check integration tab:

Deployment Instructions

Backend Deployment

cd igny8/backend
# Deploy the updated base.py file
# Restart Django server
python manage.py collectstatic --no-input
systemctl restart igny8-backend  # Or your deployment method

No Frontend Changes Needed

The frontend code is already correct and will work once the backend is deployed.

Post-Deployment Verification

  1. Clear browser cache
  2. Test all URLs mentioned in "Testing Steps"
  3. Verify each site shows its own unique data

Security Implications

Data Leakage Risk (BEFORE FIX)

  • Site A could see Site B's integration data
  • Site A could trigger syncs that affect Site B
  • Content from Site A could be pushed to Site B
  • API keys from one site visible to other sites

Data Isolation (AFTER FIX)

  • Each site only sees its own integrations
  • Syncs are properly isolated per site
  • Content stays within its designated site
  • API keys properly scoped to their site

Connection Test Bug (Also Fixed)

The connection test was showing "connected" even when the plugin was deactivated because it only checked if WordPress REST API was reachable, not if the plugin could communicate back.

Fix: Modified WordPressIntegrationForm.tsx to check fully_functional instead of just success.

Files Changed

  1. igny8/backend/igny8_core/api/base.py - Site filtering parameter fix
  2. igny8/frontend/src/components/sites/WordPressIntegrationForm.tsx - Connection test improvement

Conclusion

This was a CRITICAL data isolation bug that violated fundamental multi-tenancy principles. The fix is simple but essential:

Always verify that query parameter names match between frontend and backend!

The bug has been fixed and proper site isolation is now enforced throughout the application.


Priority: DEPLOY IMMEDIATELY
Risk: HIGH (data isolation violation)
Complexity: LOW (single line change)
Testing: REQUIRED before production deployment