Skip to content

fix(db): stop findDbPath walk at cwd when no git ceiling - #1193

Merged
carlos-alm merged 3 commits into
mainfrom
fix/find-db-path-ceiling
May 22, 2026
Merged

fix(db): stop findDbPath walk at cwd when no git ceiling#1193
carlos-alm merged 3 commits into
mainfrom
fix/find-db-path-ceiling

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

  • findDbPath no longer walks past cwd when not in a git repo, preventing stale .codegraph/ in unrelated parents (e.g. /private/tmp/, $HOME/) from being silently picked up.
  • Surfaced as the "Phase 0 footgun" in the v3.10.1-dev.80 dogfood report (§10.6): running codegraph from /tmp/dogfood-… attached to a stale /private/tmp/.codegraph/graph.db left over from a previous unrelated session.
  • Git-rooted case is unchanged — the git toplevel still acts as the ceiling.

Trade-off

Users running codegraph from a subdirectory of a non-git "project" used to auto-discover a parent .codegraph/. They now need to cd to the project root, git init, or pass -d/--db. This aligns with codegraph's git-centric design and removes the silent-attachment footgun.

Test plan

  • npx vitest run tests/unit/db.test.ts — 26 passed (including new regression test "does not pick up stale parent .codegraph/ when no git repo exists" and all existing git-ceiling tests)
  • npx vitest run tests/unit/db.test.ts tests/unit/snapshot.test.ts — 55 passed
  • npx vitest run tests/integration/structure.test.ts tests/integration/cli.test.ts — 45 passed
  • npm run build — succeeds
  • Biome lint clean on changed files
  • Manual smoke: from /tmp/cg-smoke-parent/inner/ with stale /tmp/cg-smoke-parent/.codegraph/graph.db → returns /private/tmp/cg-smoke-parent/inner/.codegraph/graph.db (not the parent)
  • Manual smoke: from inside a git worktree → returns the worktree's .codegraph/graph.db (unchanged behavior)

When findRepoRoot() returns null, the walk used to climb to /, which
could silently attach to a stale .codegraph/ in an unrelated parent —
e.g. /private/tmp/.codegraph/ leaking into every /tmp/foo/ run, or
$HOME/.codegraph/ leaking into every scratch dir under $HOME (the
"Phase 0 footgun" from the v3.10.1-dev.80 dogfood report, §10.6).

Outside a git repo, cwd is now the first (and only) directory we'll
check. Users running codegraph in non-git project subdirectories
must either cd to the project root, git init, or pass -d/--db.
@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Claude finished @carlos-alm's task —— View job


PR Review: fix(db): stop findDbPath walk at cwd when no git ceiling

Root Cause Analysis

Problem Being Solved: This PR fixes a critical security footgun where findDbPath could silently attach to stale .codegraph/ directories from unrelated parent directories when running outside a git repository. This was surfaced as the "Phase 0 footgun" in v3.10.1-dev.80 dogfood report (§10.6), where running codegraph from /tmp/dogfood-… attached to a leftover /private/tmp/.codegraph/graph.db from an unrelated session.

Why This Approach: The fix adds an early exit condition in the directory traversal loop when !ceiling (no git repo), stopping at the current working directory rather than walking up to the filesystem root. This prevents accidental attachment to unrelated databases while preserving the git-rooted behavior. The approach is surgical, well-justified, and aligns with codegraph's git-centric design philosophy.

Risk Assessment: ✅ LOW RISK. This is a targeted security fix with comprehensive test coverage. The behavioral change only affects non-git scenarios and makes the tool more predictable.

Phase 2: Configuration Change Detection

PASSED: No configuration, linting, or build changes detected. Only functional code and corresponding tests modified.

Phase 3: Test Integrity Review

EXCELLENT: New regression test 'does not pick up stale parent .codegraph/ when no git repo exists' directly validates the fixed behavior with proper setup/teardown. Existing git-ceiling tests remain unchanged, ensuring no regression in normal git workflows. Test design is thorough with realistic directory structures and proper mocking.

Phase 4: Code Quality Assessment

Implementation Quality: ⭐⭐⭐⭐☆

  • Clean 8-line fix with clear intent and excellent comments explaining the security rationale
  • Proper debug logging for troubleshooting (debug('findDbPath: no git ceiling, stopping at ${dir}'))
  • Maintains existing behavior for git-rooted scenarios
  • No performance impact (early exit reduces unnecessary traversal)

Minor observation: The fix location at src/db/connection.ts:295-302 is architecturally correct, sitting between the git ceiling check and the parent directory traversal loop.

Backlog Compliance

  • Zero-dep: ✅ — No new runtime dependencies added
  • Foundation-aligned: ✅ — Fully compliant with all principles. Enhances P1 (always-current) by preventing stale DB attachment, supports P4 (zero-cost core) with improved safety
  • Problem-fit: 4/5 — Directly prevents agent confusion from wrong database attachment, reducing token waste from analyzing unrelated codebases
  • Breaking: No — Purely additive safety improvement. Users in affected scenarios get more predictable behavior, not breakage

Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Trade-off Assessment

The noted trade-off is acceptable and well-communicated: Users running codegraph from subdirectories of non-git "projects" must now cd to project root, git init, or pass -d/--db. This trade-off:

  1. Aligns with codegraph's git-centric design
  2. Eliminates silent-attachment security footgun
  3. Makes behavior more predictable and explicit
  4. Is properly documented in the PR description

Critical Concerns

None identified. This is a well-executed security fix with appropriate testing and clear documentation.

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: High-quality security fix that eliminates a real footgun with minimal behavioral impact. Excellent test coverage, clear implementation, and proper architectural placement. The trade-off is justified and well-communicated. This directly improves the reliability of codegraph for AI agents by preventing database cross-contamination.

Strong approval recommended — this fixes a genuine security/reliability issue that could cause significant confusion for AI coding assistants.

@greptile-apps

greptile-apps Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a path-discovery footgun in findDbPath where, with no git repo present, the upward directory walk would continue past cwd all the way to /, silently attaching to a stale .codegraph/graph.db from an unrelated ancestor (e.g. /private/tmp/ or $HOME/). The fix is a single targeted guard that stops the walk after checking cwd when no git ceiling is available.

  • src/db/connection.ts: Adds a !ceiling early-break to the discovery loop immediately after the existing git-ceiling check, limiting non-git traversal to cwd only.
  • tests/unit/db.test.ts: Adds a regression test that plants a stale DB in a parent temp dir, sets cwd to an inner directory, confirms git is absent, and asserts the returned path is the cwd-local default — not the stale parent path.

Confidence Score: 5/5

Safe to merge — the change is a single-line guard with no impact on the git-rooted path, and the regression test directly covers the fixed scenario.

The fix is a minimal, well-placed guard that only affects the non-git code path. The git-ceiling path is entirely unchanged. The new regression test accurately reproduces the stale-parent attachment scenario and passes on all platforms because both sides of the path comparison derive from the same unresolved os.tmpdir() value. No pre-existing tests are affected.

No files require special attention.

Important Files Changed

Filename Overview
src/db/connection.ts Adds a !ceiling break after the existing git-ceiling stop, cleanly preventing upward traversal past cwd when outside a git repo; ordering and fallback logic are both correct.
tests/unit/db.test.ts New regression test follows existing patterns (mock cwd, reset cache, assert no stale-parent pickup); path comparisons are consistent between os.tmpdir()-derived paths and the process.cwd() fallback across platforms.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[findDbPath called] --> B{customPath provided?}
    B -- Yes --> C[return path.resolve customPath]
    B -- No --> D[findRepoRoot → ceiling]
    D --> E[dir = realpathSync cwd]
    E --> F{candidate exists?\ndir/.codegraph/graph.db}
    F -- Yes --> G[return candidate]
    F -- No --> H{ceiling set AND\ndir == ceiling?}
    H -- Yes --> I[break: git ceiling reached]
    H -- No --> J{ceiling is null?\nno git repo}
    J -- Yes --> K[break: stop at cwd NEW BEHAVIOR]
    J -- No --> L[dir = parent dir]
    L --> M{parent == dir?\nat filesystem root}
    M -- Yes --> N[break: hit root]
    M -- No --> F
    I --> O[base = ceiling OR cwd]
    K --> O
    N --> O
    O --> P[return base/.codegraph/graph.db]
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into fix/find-db-pat..." | Re-trigger Greptile

@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

1 functions changed99 callers affected across 67 files

  • findDbPath in src/db/connection.ts:262 (102 transitive callers)

@carlos-alm
carlos-alm merged commit a9cd175 into main May 22, 2026
21 checks passed
@carlos-alm
carlos-alm deleted the fix/find-db-path-ceiling branch May 22, 2026 01:48
@github-actions github-actions Bot locked and limited conversation to collaborators May 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant