TryBugHunt

The Leaky Token Bucket

Mediumpython

In-Memory Rate Limiter with Cross-Client State Leakage

0:00
Step 1: Test Traffic & Expose Flaw
"""
Token Bucket Rate Limiter Service
Handles per-client request throttling with refill mechanism.
"""

class TokenBucketLimiter:
    def __init__(self, capacity=5, refill_rate=1.0, default_bucket={"tokens": 5.0, "last_refill": 0.0}):
        self.capacity = capacity
        self.refill_rate = refill_rate
        # AI Attempt: Uses default dictionary for new clients
        self.default_bucket = default_bucket
        self.buckets = {}

    def _refill(self, bucket, now):
        elapsed = max(0.0, now - bucket["last_refill"])
        new_tokens = elapsed * self.refill_rate
        if new_tokens > 0:
            bucket["tokens"] = min(float(self.capacity), bucket["tokens"] + new_tokens)
            bucket["last_refill"] = now

    def allow_request(self, client_id, timestamp=0.0):
        # Retrieve existing client bucket or use default
        bucket = self.buckets.get(client_id, self.default_bucket)
        self.buckets[client_id] = bucket

        self._refill(bucket, timestamp)

        if bucket["tokens"] >= 1.0:
            bucket["tokens"] -= 1.0
            return True
        return False
Step 1: Test Traffic & Expose FlawClient-side WASM

Run a scenario below to trace requests through the gateway. Prove that Client A's burst consumption drains tokens from Client B.

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

Deep Dive: The Leaky Token Bucket

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 Python, default parameter expressions such as default_bucket={"tokens": 5.0, ...} are evaluated only once when the function is defined, not per instance instantiation. Because the dictionary is mutable, every client that falls back to this default operates on the exact same dictionary in memory, creating a silent cross-tenant quota leak.

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.