TryBugHunt

The Phantom Superadmin

Mediumjavascript

Role-Based Access Control with Shared Default Reference Leak

0:00
Step 1: Test Traffic & Expose Flaw
/**
 * Role-Based Access Control Service
 * Handles user role configuration and access verification.
 */

class PermissionChecker {
  constructor(defaultConfig = { roles: ["viewer"], isSuperAdmin: false }) {
    // AI Attempt: Stores default guest configuration
    this.defaultConfig = defaultConfig;
    this.userConfigs = new Map();
  }

  grantAdmin(userId) {
    // Retrieve existing config or fall back to default
    const config = this.userConfigs.get(userId) || this.defaultConfig;
    config.isSuperAdmin = true;
    if (!config.roles.includes("admin")) {
      config.roles.push("admin");
    }
    this.userConfigs.set(userId, config);
  }

  checkAccess(userId, requiredRole) {
    const config = this.userConfigs.get(userId) || this.defaultConfig;
    return Boolean(config.isSuperAdmin || config.roles.includes(requiredRole));
  }
}

module.exports = { PermissionChecker };
Step 1: Test Traffic & Expose FlawClient-side WASM

Run a scenario below to trace access checks. Prove that elevating an admin user grants superadmin permissions to unrelated guest users.

Choose Traffic Scenario to TestClick to simulate
Architectural Guide & Interview Notes

Deep Dive: The Phantom Superadmin

An engineering analysis of why this AI-generated Pull Request passed isolated unit tests, how multi-tenant traffic exposes the architectural flaw, and how interviewers score your response.

The Root Cause Anti-Pattern

In JavaScript, using the shallow object spread syntax { ...this.defaultConfig } copies top-level primitive values like isSuperAdmin, but leaves nested reference types like roles pointing to the original array in memory. Calling roles.push("admin") directly mutates the default guest configuration.

The Interviewer's Scoring Rubric

Candidates are assessed on whether they jump to trial-and-error editing or follow a hypothesis-driven approach. A "Strong Hire" candidate restates the data flow between modules, explains why single-client unit tests passed, crafts an adversarial probe showing cross-tenant leakage, and implements a surgical 1-line patch without breaking existing contracts.

Candidate Strategy for the Code Comprehension Round

  1. 1Map Module ContractsTrace how the gateway invokes the underlying service. Note what data is passed by reference vs. by value.
  2. 2Break It With An Adversarial ProbeSimulate concurrent or sequential traffic across multiple identities to force shared state mutation.
  3. 3Deliver a Surgical PatchMake the minimal required diff to ensure proper per-client state isolation without refactoring unnecessary files.