Skip to content

[Bug]: Session manager cache checks TTL but never deletes expired entries #6761

@coygeek

Description

@coygeek

CVSS Assessment

Metric Value
Score 6.5 / 10.0
Severity Medium
Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

CVSS v3.1 Calculator

Summary

The SESSION_MANAGER_CACHE checks TTL on read but never deletes expired entries, causing a slow memory leak where stale cache entries accumulate indefinitely.

Affected Code

File: src/agents/pi-embedded-runner/session-manager-cache.ts:10

const SESSION_MANAGER_CACHE = new Map<string, SessionManagerCacheEntry>();

function isSessionManagerCached(sessionFile: string): boolean {
  // ...
  const entry = SESSION_MANAGER_CACHE.get(sessionFile);
  if (!entry) {
    return false;
  }
  const now = Date.now();
  const ttl = getSessionManagerTtl();
  return now - entry.loadedAt <= ttl;  // Checks TTL but doesn't delete!
}

export function trackSessionManagerAccess(sessionFile: string): void {
  // ...
  SESSION_MANAGER_CACHE.set(sessionFile, {
    sessionFile,
    loadedAt: now,
  });
  // No pruning of expired entries anywhere
}

Attack Surface

How is this reached?

  • Network (HTTP/WebSocket endpoint, API call)
  • Adjacent Network (same LAN, requires network proximity)
  • Local (local file, CLI argument, environment variable)
  • Physical (requires physical access to machine)

Authentication required?

  • None (unauthenticated/public access)
  • Low (any authenticated user)
  • High (admin/privileged user only)

Entry point: Agent session creation and access tracking.

Exploit Conditions

Complexity:

  • Low (no special conditions, works reliably)
  • High (requires race condition, specific config, or timing)

User interaction:

  • None (automatic, no victim action needed)
  • Required (victim must click, visit, or perform action)

Prerequisites: Gateway must be running embedded agents with session tracking.

Impact Assessment

Scope:

  • Unchanged (impact limited to vulnerable component)
  • Changed (can affect other components, escape sandbox)

What can an attacker do?

Impact Type Level Description
Confidentiality None No data disclosure
Integrity None No data modification
Availability High Slow memory leak causes eventual OOM

Steps to Reproduce

  1. Run gateway with embedded agent sessions
  2. Create many unique session files over time
  3. Each session file path adds an entry to SESSION_MANAGER_CACHE
  4. TTL expires, but entries remain in the Map
  5. isSessionManagerCached returns false for expired entries, but doesn't delete them
  6. Map grows monotonically over gateway lifetime
  7. Eventually OOM occurs

Recommended Fix

Delete expired entries when checking TTL:

function isSessionManagerCached(sessionFile: string): boolean {
  const entry = SESSION_MANAGER_CACHE.get(sessionFile);
  if (!entry) {
    return false;
  }
  const now = Date.now();
  const ttl = getSessionManagerTtl();
  if (now - entry.loadedAt > ttl) {
    SESSION_MANAGER_CACHE.delete(sessionFile);  // Delete expired entry
    return false;
  }
  return true;
}

Or add periodic pruning:

function pruneExpiredEntries(): void {
  const now = Date.now();
  const ttl = getSessionManagerTtl();
  for (const [sessionFile, entry] of SESSION_MANAGER_CACHE) {
    if (now - entry.loadedAt > ttl) {
      SESSION_MANAGER_CACHE.delete(sessionFile);
    }
  }
}

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstaleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions