Skip to content

Bound resolver caches, validate MCP input sizes, add integration tests#213

Open
srikaanthh wants to merge 1 commit into
colbymchenry:mainfrom
srikaanthh:fix/cache-bounds-mcp-limits-integration-tests
Open

Bound resolver caches, validate MCP input sizes, add integration tests#213
srikaanthh wants to merge 1 commit into
colbymchenry:mainfrom
srikaanthh:fix/cache-bounds-mcp-limits-integration-tests

Conversation

@srikaanthh
Copy link
Copy Markdown

Summary

Three reliability fixes uncovered in a recent audit of the codebase:

  • Unbounded resolver cache growth (OOM risk)ReferenceResolver held seven per-resolver Map caches (nodeCache, fileCache, nameCache, lowerNameCache, qualifiedNameCache, importMappingCache, reExportCache) that grew without limit. On 20k+ file codebases the resident set ballooned until the process OOM'd. Replaced with a bounded LRU (src/resolution/lru-cache.ts): 5,000 entries per metadata cache, 1,000 for the heavier file-content cache. Configurable via CODEGRAPH_RESOLVER_CACHE_SIZE for very large/small projects.

  • No input size limits on MCP toolsToolHandler.execute had no guard on query / task / symbol / projectPath / path / pattern lengths, so a malicious or buggy MCP client could ship a 100MB string and force a full FTS5 scan or OOM the server. Added centralized bounds: 10,000 chars for free-form inputs, 4,096 for path-shaped inputs, rejected with a clear error before any DB work runs.

  • Missing end-to-end integration tests — added __tests__/integration/ with three suites: the full pipeline (init → index → resolve → search → callers → context → sync) against a 120-file synthetic project, parse-error resilience, idempotent sync, LRU eviction correctness, and MCP input-limit rejection across every affected tool entry point. 19 new tests, all passing.

Test plan

  • npx vitest run __tests__/integration/ — 19/19 pass
  • npx tsc --noEmit — clean
  • No regressions in resolution.test.ts, mcp-initialize.test.ts, sync.test.ts, symbol-lookup.test.ts, watcher.test.ts
  • npm run build — clean

Files changed

File Change
src/resolution/lru-cache.ts new — small LRU implementation backed by Map's insertion order
src/resolution/index.ts swap unbounded Map caches → bounded LRUCache; env override
src/mcp/tools.ts validateString now bounds to 10k chars; new validateOptionalPath (4k chars); cross-cutting validation in execute()
__tests__/integration/lru-cache.test.ts new — 7 tests for eviction correctness incl. heavy-churn regression
__tests__/integration/mcp-input-limits.test.ts new — 9 tests rejecting oversize inputs across all tools
__tests__/integration/full-pipeline.test.ts new — 3 tests covering the full pipeline, parse-error resilience, and idempotent sync

… tests

Three reliability fixes uncovered in the recent audit:

1. **Unbounded resolver cache growth (OOM risk)** —
   `src/resolution/index.ts` held seven per-resolver `Map` caches that
   grew without limit, so on 20k+ file codebases the resident set
   ballooned until the process OOM'd. Replaced them with a simple
   LRU cache (`src/resolution/lru-cache.ts`) bounded to 5,000 entries
   per cache (1,000 for the heavier file-content cache). Configurable
   via `CODEGRAPH_RESOLVER_CACHE_SIZE` for very large/small projects.

2. **No input size limits on MCP tools** — `ToolHandler.execute` had no
   guard on query/task/symbol/projectPath/path/pattern lengths, so a
   malicious or buggy MCP client could ship a 100MB string and force
   a full FTS5 scan or OOM the server. Added centralized bounds:
   10,000 chars for free-form inputs, 4,096 for path-shaped inputs.

3. **Missing end-to-end integration tests** — added
   `__tests__/integration/` with three suites covering: the full
   pipeline (init → index → resolve → search → callers → context →
   sync) on a 120-file synthetic project, LRU eviction correctness,
   and MCP input-limit rejection across every affected tool entry
   point. 19 new tests, all passing.

Full test suite: 19 new tests pass; no regressions in the existing
suites that ran against this change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant