Improper Isolation or Compartmentalization

Description

Improper Isolation or Compartmentalization occurs when an application fails to properly separate components, processes, or data that should be isolated from each other. This includes running components with more privileges than needed, failing to use sandboxes or containers, sharing resources between security domains, and not implementing defense in depth. A compromise of one component leads to compromise of others.

Risk

Compromise of one component leads to full system compromise. Privilege escalation from low-privilege to high-privilege components. Cross-tenant data access in multi-tenant systems. Lateral movement through shared resources. Sensitive data exposed through improper boundaries. Malware spread through uncontained processes.

Solution

Implement proper process isolation using containers or sandboxes. Apply principle of least privilege. Use separate databases/schemas per tenant. Implement network segmentation. Use capability-based security. Separate authentication from business logic. Apply defense in depth across all layers.

Common Consequences

ImpactDetails
ConfidentialityScope: Data Breach

Data from one domain accessed by another.
IntegrityScope: Cross-Contamination

One component corrupts another's data.
AvailabilityScope: Cascade Failure

One failure brings down entire system.

Example Code + Solution Code

Vulnerable Code

// VULNERABLE: No isolation between components
public class VulnerableMonolithicApp {

    // All components share same process and privileges
    private UserService userService;
    private PaymentService paymentService;
    private AdminService adminService;
    private FileService fileService;

    // VULNERABLE: Payment service can access admin functions
    public void processPayment(PaymentRequest request) {
        // Payment code runs with full application privileges
        // Can access userService, adminService, fileService
        paymentService.process(request);

        // If payment code is compromised, attacker has access to everything
    }

    // VULNERABLE: Single database, all services share access
    private DataSource sharedDatabase;  // Everyone uses same connection

    public void storeData(String component, String data) {
        // All components write to same tables
        // No row-level security
        sharedDatabase.execute("INSERT INTO data ...");
    }
}

// VULNERABLE: Multi-tenant without isolation
public class VulnerableMultiTenantService {

    private DataSource db;  // Single shared database

    public List<Order> getOrders(String tenantId) {
        // VULNERABLE: Relies only on WHERE clause for isolation
        // SQL injection or bug could expose other tenants' data
        return db.query(
            "SELECT * FROM orders WHERE tenant_id = ?",
            tenantId
        );
    }

    // VULNERABLE: Shared file storage
    public void saveFile(String tenantId, String filename, byte[] data) {
        // All tenants share same directory
        // Path traversal could access other tenants' files
        Path path = Paths.get("/data/uploads/" + filename);
        Files.write(path, data);
    }
}
# VULNERABLE: Python without process isolation
import os
from flask import Flask, request

app = Flask(__name__)

# VULNERABLE: All code runs in same process with same privileges
class MonolithicApp:
    def __init__(self):
        # Single database connection shared everywhere
        self.db = Database()

        # No separation of concerns
        self.user_service = UserService(self.db)
        self.payment_service = PaymentService(self.db)
        self.admin_service = AdminService(self.db)

    # VULNERABLE: Payment processing can access admin DB
    def process_payment(self, payment_data):
        # If this is exploited, attacker can access admin functions
        result = self.payment_service.process(payment_data)

        # Same process, can call admin functions
        self.admin_service.do_something()

# VULNERABLE: Shell commands executed without sandboxing
@app.route('/convert', methods=['POST'])
def convert_file_vulnerable():
    filename = request.form['filename']

    # VULNERABLE: Executes in main process context
    # Can access all application files and resources
    os.system(f"convert {filename} output.pdf")

    return "Converted"

# VULNERABLE: Multi-tenant with shared resources
class VulnerableMultiTenant:
    def __init__(self):
        self.shared_db = Database()
        self.shared_cache = RedisCache()
        self.shared_storage = FileStorage('/data')

    def get_tenant_data(self, tenant_id, query):
        # VULNERABLE: Only application-level filtering
        # Database doesn't enforce isolation
        return self.shared_db.execute(
            f"SELECT * FROM data WHERE tenant_id = '{tenant_id}' AND {query}"
        )
// VULNERABLE: Node.js monolithic without isolation
const express = require('express');
const app = express();

// VULNERABLE: All services in same process
class MonolithicServer {
    constructor() {
        this.db = new Database();

        // Everything shares same resources
        this.userService = new UserService(this.db);
        this.paymentService = new PaymentService(this.db);
        this.fileService = new FileService(this.db);
    }

    // VULNERABLE: Code execution without sandboxing
    executeUserCode(code) {
        // Runs in same context as application
        // Can access all global objects
        return eval(code);
    }
}

// VULNERABLE: Multi-tenant without database isolation
class MultiTenantService {
    constructor() {
        this.pool = new DatabasePool();  // Shared pool
    }

    async getData(tenantId, table) {
        // VULNERABLE: Tenant isolation only through queries
        // Not enforced at database level
        return await this.pool.query(
            `SELECT * FROM ${table} WHERE tenant_id = $1`,
            [tenantId]
        );
    }

    // VULNERABLE: Shared secrets manager
    async getSecret(tenantId, secretName) {
        // All tenants use same secrets store
        // Naming convention is only protection
        return await secretsManager.get(`${tenantId}/${secretName}`);
    }
}
// VULNERABLE: Go without proper isolation
package main

// VULNERABLE: Monolithic design
type Application struct {
    db           *sql.DB  // Single shared database
    userService  *UserService
    adminService *AdminService
    config       *Config  // Shared config with all secrets
}

// VULNERABLE: All requests handled in same process
func (app *Application) handleRequest(w http.ResponseWriter, r *http.Request) {
    // User-facing code can access admin service
    // No process boundary
    app.userService.HandleUser(w, r)
}

// VULNERABLE: Executing untrusted code
func (app *Application) runPlugin(pluginCode string) {
    // Runs with full application privileges
    // No sandboxing
    plugin := LoadPlugin(pluginCode)
    plugin.Execute(app)  // Plugin has access to everything
}

// VULNERABLE: Multi-tenant shared resources
func (app *Application) getTenantData(tenantID string) []Data {
    // No database-level tenant isolation
    rows, _ := app.db.Query(
        "SELECT * FROM data WHERE tenant_id = $1",
        tenantID,
    )
    return parseRows(rows)
}

Fixed Code

// SAFE: Microservices with proper isolation
public class IsolatedPaymentService {

    // SAFE: Dedicated database with limited access
    private final DataSource paymentDatabase;

    // SAFE: Isolated configuration
    private final PaymentConfig config;

    public IsolatedPaymentService() {
        // Only payment-related database access
        this.paymentDatabase = DataSourceBuilder.create()
            .url(System.getenv("PAYMENT_DB_URL"))
            .username(System.getenv("PAYMENT_DB_USER"))
            .build();

        // Limited configuration
        this.config = new PaymentConfig();
    }

    // SAFE: Can only perform payment operations
    public PaymentResult process(PaymentRequest request) {
        // No access to user service, admin service, etc.
        return processPayment(request);
    }
}

// SAFE: Multi-tenant with database-level isolation
public class IsolatedMultiTenantService {

    private final Map<String, DataSource> tenantDatabases;

    // SAFE: Separate database per tenant
    public DataSource getTenantDatabase(String tenantId) {
        return tenantDatabases.computeIfAbsent(tenantId, id -> {
            // Each tenant gets their own database
            return DataSourceBuilder.create()
                .url(String.format("jdbc:postgresql://db/%s_db", id))
                .build();
        });
    }

    public List<Order> getOrders(String tenantId) {
        // SAFE: Uses tenant-specific database
        DataSource ds = getTenantDatabase(tenantId);
        // Even SQL injection can't access other tenants
        return ds.query("SELECT * FROM orders");
    }

    // SAFE: Isolated file storage per tenant
    public void saveFile(String tenantId, String filename, byte[] data) {
        // Validate filename
        if (!isValidFilename(filename)) {
            throw new SecurityException("Invalid filename");
        }

        // Each tenant has separate storage
        Path tenantDir = Paths.get("/data/tenants", tenantId, "files");
        Path filePath = tenantDir.resolve(filename).normalize();

        // Verify within tenant directory
        if (!filePath.startsWith(tenantDir)) {
            throw new SecurityException("Path traversal detected");
        }

        Files.write(filePath, data);
    }
}

// SAFE: Using containers for process isolation
@Configuration
public class IsolatedProcessConfig {

    @Bean
    public CodeExecutor sandboxedExecutor() {
        // Execute untrusted code in isolated container
        return new DockerExecutor(
            DockerConfig.builder()
                .image("sandbox:latest")
                .memoryLimit("256m")
                .cpuLimit(0.5)
                .networkMode("none")  // No network access
                .readOnlyRootFilesystem(true)
                .build()
        );
    }
}
# SAFE: Python with proper isolation
import os
from multiprocessing import Process
import docker

# SAFE: Microservice with limited scope
class IsolatedPaymentService:
    def __init__(self):
        # Only payment-specific database
        self.db = Database(os.environ['PAYMENT_DB_URL'])

        # No access to other services' resources

    def process_payment(self, payment_data):
        # Can only perform payment operations
        return self.db.execute_payment(payment_data)

# SAFE: Sandboxed code execution
class SandboxedExecutor:
    def __init__(self):
        self.docker_client = docker.from_env()

    def execute_untrusted_code(self, code, timeout=30):
        # Execute in isolated container
        container = self.docker_client.containers.run(
            image='python-sandbox:latest',
            command=['python', '-c', code],
            detach=True,
            mem_limit='256m',
            cpu_period=100000,
            cpu_quota=50000,  # 50% CPU
            network_mode='none',  # No network
            read_only=True,
            security_opt=['no-new-privileges'],
            cap_drop=['ALL']
        )

        try:
            result = container.wait(timeout=timeout)
            logs = container.logs()
            return logs.decode()
        finally:
            container.remove(force=True)

# SAFE: Multi-tenant with database isolation
class IsolatedMultiTenant:
    def __init__(self):
        self.tenant_dbs = {}
        self.tenant_storage = {}

    def get_tenant_db(self, tenant_id):
        if tenant_id not in self.tenant_dbs:
            # Each tenant gets separate database
            self.tenant_dbs[tenant_id] = Database(
                f"postgresql://db/{tenant_id}_db"
            )
        return self.tenant_dbs[tenant_id]

    def get_tenant_data(self, tenant_id, query):
        # Uses tenant-specific database
        db = self.get_tenant_db(tenant_id)
        # Can't access other tenants' data even with SQL injection
        return db.execute(query)

    def get_tenant_storage(self, tenant_id):
        # Isolated storage per tenant
        tenant_path = f"/data/tenants/{tenant_id}"
        if tenant_id not in self.tenant_storage:
            # Create chroot-like isolation
            self.tenant_storage[tenant_id] = IsolatedStorage(tenant_path)
        return self.tenant_storage[tenant_id]

# SAFE: Process isolation for sensitive operations
class SecureProcessor:
    def process_sensitive_data(self, data):
        # Run in separate process with limited privileges
        def isolated_work(input_queue, output_queue):
            # Drop privileges
            os.setgid(65534)  # nobody
            os.setuid(65534)

            # Process data
            result = do_processing(input_queue.get())
            output_queue.put(result)

        from multiprocessing import Queue
        input_q, output_q = Queue(), Queue()
        input_q.put(data)

        p = Process(target=isolated_work, args=(input_q, output_q))
        p.start()
        p.join(timeout=30)

        return output_q.get()
// SAFE: Node.js with process isolation
const { Worker } = require('worker_threads');
const { VM } = require('vm2');

// SAFE: Sandboxed code execution
class SandboxedExecutor {
    executeUntrustedCode(code, timeout = 5000) {
        // Use VM2 for sandboxed execution
        const vm = new VM({
            timeout,
            sandbox: {
                // Only expose safe APIs
                console: {
                    log: (...args) => console.log('[sandbox]', ...args)
                }
            },
            eval: false,
            wasm: false
        });

        try {
            return vm.run(code);
        } catch (error) {
            return { error: error.message };
        }
    }

    // SAFE: Execute in separate worker thread
    async executeInWorker(code) {
        return new Promise((resolve, reject) => {
            const worker = new Worker(`
                const { parentPort } = require('worker_threads');
                try {
                    const result = eval(${JSON.stringify(code)});
                    parentPort.postMessage({ result });
                } catch (error) {
                    parentPort.postMessage({ error: error.message });
                }
            `, { eval: true });

            const timeout = setTimeout(() => {
                worker.terminate();
                reject(new Error('Execution timeout'));
            }, 5000);

            worker.on('message', (msg) => {
                clearTimeout(timeout);
                resolve(msg);
            });
        });
    }
}

// SAFE: Multi-tenant with proper isolation
class IsolatedMultiTenantService {
    constructor() {
        this.tenantConnections = new Map();
    }

    getTenantConnection(tenantId) {
        if (!this.tenantConnections.has(tenantId)) {
            // Each tenant gets dedicated database
            const connection = new Database({
                host: 'db',
                database: `tenant_${tenantId}`,
                user: `tenant_${tenantId}_user`,
                // Tenant-specific credentials
                password: process.env[`TENANT_${tenantId}_DB_PASS`]
            });
            this.tenantConnections.set(tenantId, connection);
        }
        return this.tenantConnections.get(tenantId);
    }

    async getData(tenantId, query) {
        // Uses tenant-specific database
        const db = this.getTenantConnection(tenantId);
        return await db.query(query);
    }
}

Exploited in the Wild

Container Escapes

Lack of proper container isolation exploited for host access.

Multi-Tenant Data Breaches

Shared database access leading to cross-tenant exposure.

Lateral Movement

Compromise of one component leading to full system breach.


Tools to test/exploit

  • Container security scanners.

  • Lateral movement detection tools.

  • Multi-tenant isolation testing.


CVE Examples

  • CVE-2020-15257: Container escape via shared namespaces.

  • Cloud multi-tenancy isolation failures.


References

  1. MITRE. "CWE-653: Improper Isolation or Compartmentalization." https://cwe.mitre.org/data/definitions/653.html

  2. NIST. "Security Isolation Guidelines."