Skip to content

test: cover resolveSubagentPath candidates#331

Open
looooown2006 wants to merge 2 commits intoexospherehost:mainfrom
looooown2006:test/resolve-subagent-path-328
Open

test: cover resolveSubagentPath candidates#331
looooown2006 wants to merge 2 commits intoexospherehost:mainfrom
looooown2006:test/resolve-subagent-path-328

Conversation

@looooown2006
Copy link
Copy Markdown

@looooown2006 looooown2006 commented May 9, 2026

Summary

Add unit coverage for resolveSubagentPath(...).

Changes

  • Added __tests__/lib/resolve-subagent-path.test.ts.
  • Covered all documented candidate lookup paths:
    • project-level agent-<id>.jsonl
    • session-level agent-<id>.jsonl
    • session subagents/agent-<id>.jsonl
  • Covered the null result when no candidate exists.
  • Covered a path-traversal-style agentId by creating an existing candidate outside projectsPath and verifying it is still refused.

Tests

  • bun run test:run __tests__/lib/resolve-subagent-path.test.ts
  • git diff --cached --check

Full-suite note: bun run test:run was also run in this Windows workspace after repairing the local Bun test entrypoint. The new resolve-subagent-path test passed, but the full suite is not green locally due to unrelated Windows/path and incomplete local dependency-install issues (for example POSIX path expectation failures and missing next/* imports after bun install repeatedly timed out).

Refs #328.

Summary by CodeRabbit

  • Tests
    • Enhanced test coverage for subagent path resolution functionality with comprehensive validation of candidate locations and security regression testing.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Warning

Rate limit exceeded

@looooown2006 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 39 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f55ccf9-99e9-474d-9e7d-ec9dece00080

📥 Commits

Reviewing files that changed from the base of the PR and between c2b5df6 and 53f51a9.

📒 Files selected for processing (1)
  • __tests__/lib/resolve-subagent-path.test.ts
📝 Walkthrough

Walkthrough

This PR adds a comprehensive Vitest test suite for the resolveSubagentPath function. The tests establish a temporary filesystem fixture, verify path resolution across three candidate locations in priority order, and include a regression test for path traversal vulnerability prevention.

Changes

Subagent Path Resolution Tests

Layer / File(s) Summary
Test Suite Setup
__tests__/lib/resolve-subagent-path.test.ts
Per-test temporary directory under projects/<project>/<session> with cleanup. Local touch() helper creates parent directories and empty files.
Path Resolution Assertions
__tests__/lib/resolve-subagent-path.test.ts
Tests verify resolveSubagentPath resolves to candidate 1 (project-level agent log), candidate 2 (session-level agent log), candidate 3 (session-level subagents log), and returns null when no candidates exist.
Path Traversal Security
__tests__/lib/resolve-subagent-path.test.ts
Regression test confirms function returns null for agentId values containing traversal segments (e.g., ../..) even when an escaped candidate file exists outside the projects directory.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Poem

🐰 A test suite hops into place,
Checking paths with filesystem grace,
Three candidates tried, traversals denied,
Subagents resolving without a trace! 🛡️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding test coverage for the resolveSubagentPath function, which is the primary purpose of this PR.
Description check ✅ Passed The description covers all key aspects: summary of changes, detailed coverage of test cases, and test execution results. It references the related issue (#328) and provides context about local testing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
__tests__/lib/resolve-subagent-path.test.ts (1)

32-51: ⚡ Quick win

Consider testing candidate priority order.

The current tests verify each candidate location in isolation, but don't confirm that candidate 1 is preferred when multiple candidates exist. Adding a test that creates all three candidates and verifies candidate 1 is returned would strengthen confidence in the priority logic.

📋 Example priority test
it("returns candidate 1 when all candidates exist", async () => {
  const candidate1 = join(projectsPath, projectName, `agent-${agentId}.jsonl`);
  const candidate2 = join(projectsPath, projectName, sessionId, `agent-${agentId}.jsonl`);
  const candidate3 = join(projectsPath, projectName, sessionId, "subagents", `agent-${agentId}.jsonl`);
  
  await touch(candidate3);
  await touch(candidate2);
  await touch(candidate1);

  await expect(resolveSubagentPath(projectsPath, projectName, sessionId, agentId)).resolves.toBe(candidate1);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@__tests__/lib/resolve-subagent-path.test.ts` around lines 32 - 51, Add a test
that verifies candidate priority by creating all three possible files and
asserting resolveSubagentPath returns the project-level path (candidate 1). Use
the existing helper touch to create candidate3 (join(projectsPath, projectName,
sessionId, "subagents", `agent-${agentId}.jsonl`)), candidate2
(join(projectsPath, projectName, sessionId, `agent-${agentId}.jsonl`)), then
candidate1 (join(projectsPath, projectName, `agent-${agentId}.jsonl`)) and call
await expect(resolveSubagentPath(projectsPath, projectName, sessionId,
agentId)).resolves.toBe(candidate1) to confirm priority.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@__tests__/lib/resolve-subagent-path.test.ts`:
- Around line 57-64: The test currently leaves an escaped file outside
fixtureRoot because traversalAgentId ("../../../../escape") normalizes above
projectsPath; change the fixture so the `escapedCandidate` path normalizes
inside `fixtureRoot` while still being outside `projectsPath` (e.g., deepen the
temp fixture directory structure and pick a traversalAgentId that climbs out of
`projectsPath` but remains within the fixtureRoot tree), ensure any directories
for `escapedCandidate` are created before calling `touch`, and/or explicitly
remove the created escaped file in the test teardown (afterEach) to guarantee
cleanup; update references in the test to use the adjusted
traversalAgentId/fixture layout (symbols: traversalAgentId, escapedCandidate,
projectsPath, fixtureRoot, touch, afterEach, resolveSubagentPath).

---

Nitpick comments:
In `@__tests__/lib/resolve-subagent-path.test.ts`:
- Around line 32-51: Add a test that verifies candidate priority by creating all
three possible files and asserting resolveSubagentPath returns the project-level
path (candidate 1). Use the existing helper touch to create candidate3
(join(projectsPath, projectName, sessionId, "subagents",
`agent-${agentId}.jsonl`)), candidate2 (join(projectsPath, projectName,
sessionId, `agent-${agentId}.jsonl`)), then candidate1 (join(projectsPath,
projectName, `agent-${agentId}.jsonl`)) and call await
expect(resolveSubagentPath(projectsPath, projectName, sessionId,
agentId)).resolves.toBe(candidate1) to confirm priority.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9280d3d8-3dff-41eb-a80d-915de7878ea5

📥 Commits

Reviewing files that changed from the base of the PR and between 070a9c6 and c2b5df6.

📒 Files selected for processing (1)
  • __tests__/lib/resolve-subagent-path.test.ts

Comment on lines +57 to +64
it("does not resolve an existing candidate outside the projects path", async () => {
const traversalAgentId = "../../../../escape";
const escapedCandidate = join(projectsPath, projectName, `agent-${traversalAgentId}.jsonl`);
expect(relative(projectsPath, escapedCandidate).startsWith("..")).toBe(true);
await touch(escapedCandidate);

await expect(resolveSubagentPath(projectsPath, projectName, sessionId, traversalAgentId)).resolves.toBeNull();
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Test leak: escaped file not cleaned up.

The path traversal test creates a file outside fixtureRoot (at /tmp/escape.jsonl or similar), but the afterEach hook only removes fixtureRoot. This leaves the escaped file behind, polluting the test environment.

The calculation:

  • join(projectsPath, projectName, "agent-../../../../escape.jsonl")
  • With projectsPath = "/tmp/failproofai-subagents-XXXXXX/projects"
  • Normalizes to: /tmp/escape.jsonl (outside the fixture)
🧹 Proposed fix: deepen fixture structure to contain the escaped path
  beforeEach(async () => {
    fixtureRoot = await mkdtemp(join(tmpdir(), "failproofai-subagents-"));
-   projectsPath = join(fixtureRoot, "projects");
+   // Use a deeper structure so that even with traversal, we stay within fixtureRoot
+   projectsPath = join(fixtureRoot, "a", "b", "c", "d", "projects");
    await mkdir(join(projectsPath, projectName, sessionId, "subagents"), { recursive: true });
  });

With this change:

  • escapedCandidate normalizes to /tmp/failproofai-subagents-XXXXXX/a/b/c/escape.jsonl
  • Still outside projectsPath (satisfies line 60's assertion)
  • But inside fixtureRoot (properly cleaned up)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@__tests__/lib/resolve-subagent-path.test.ts` around lines 57 - 64, The test
currently leaves an escaped file outside fixtureRoot because traversalAgentId
("../../../../escape") normalizes above projectsPath; change the fixture so the
`escapedCandidate` path normalizes inside `fixtureRoot` while still being
outside `projectsPath` (e.g., deepen the temp fixture directory structure and
pick a traversalAgentId that climbs out of `projectsPath` but remains within the
fixtureRoot tree), ensure any directories for `escapedCandidate` are created
before calling `touch`, and/or explicitly remove the created escaped file in the
test teardown (afterEach) to guarantee cleanup; update references in the test to
use the adjusted traversalAgentId/fixture layout (symbols: traversalAgentId,
escapedCandidate, projectsPath, fixtureRoot, touch, afterEach,
resolveSubagentPath).

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