Skip to content

fix(sessions): multi-agent session path validation rejects valid cross-agent paths#18016

Merged
steipete merged 2 commits intoopenclaw:mainfrom
xinhuagu:fix/multi-agent-session-path
Feb 16, 2026
Merged

fix(sessions): multi-agent session path validation rejects valid cross-agent paths#18016
steipete merged 2 commits intoopenclaw:mainfrom
xinhuagu:fix/multi-agent-session-path

Conversation

@xinhuagu
Copy link
Contributor

@xinhuagu xinhuagu commented Feb 16, 2026

Problem

In multi-agent setups, resolvePathWithinSessionsDir rejects valid absolute session file paths that point to another agent's sessions directory when OPENCLAW_STATE_DIR differs from the state directory used when the session was originally created.

This happens because the fallback logic extracts the agent ID from the path and tries to resolve it against the current environment's state directory. When the directories don't match (e.g., after reinstall, config change, or when agents use different state dirs), the containment check fails with:

Session file path must be within sessions directory

Root Cause

The hardening in v2026.2.12 (resolvePathWithinSessionsDir) added strict containment checks. The subsequent fallback logic (resolveSiblingAgentSessionsDir + extractAgentIdFromAbsoluteSessionPath) handles cross-agent paths but only when the root state directory is consistent. When it differs, both the sibling resolution and the resolveAgentSessionsDir fallback resolve to paths under the wrong root, so containment always fails.

Fix

After the existing fallbacks are exhausted, if extractAgentIdFromAbsoluteSessionPath successfully validated that the path structurally matches .../agents/<agentId>/sessions/..., accept it directly. The structural pattern already provides sufficient containment guarantees — it ensures the path is within an agent's sessions directory hierarchy.

Testing

  • Added test: cross-agent absolute sessionFile paths resolve correctly
  • Added test: cross-agent paths work when OPENCLAW_STATE_DIR differs from stored paths
  • Added test: paths outside agent sessions directories are still rejected
  • All existing tests pass

Fixes #15410, Fixes #15565, Fixes #15468

Greptile Summary

This PR fixes resolvePathWithinSessionsDir to accept cross-agent session file paths when OPENCLAW_STATE_DIR differs from the directory used when the session was created. The fix adds a final fallback (after sibling and env-based resolution attempts are exhausted) that accepts the path if extractAgentIdFromAbsoluteSessionPath confirms it structurally matches .../agents/<agentId>/sessions/... after full path normalization.

  • The structural check relies on path.normalize(path.resolve(...)) to collapse all .. traversal sequences before verifying the agents/<id>/sessions pattern, which prevents path escapes
  • Paths that don't match the structural pattern (e.g., /etc/passwd) are still properly rejected
  • Three new tests cover: same-state-dir cross-agent resolution, different-state-dir cross-agent resolution, and rejection of paths outside agent session directories
  • The change is minimal and well-scoped to the identified root cause

Confidence Score: 4/5

  • This PR is safe to merge — the structural path validation after normalization is sound and the change is narrowly scoped.
  • The fix is minimal (4 lines + comment) and well-reasoned. Path traversal is prevented by path.normalize(path.resolve(...)) collapsing .. segments before the structural pattern check. The fallback only triggers after all existing resolution strategies fail, maintaining backward compatibility. Three tests cover the positive and negative cases. The only reason this isn't a 5 is the inherent sensitivity of path containment code — filesystem-level symlinks could theoretically bypass string-based containment, but this is a pre-existing concern not introduced by this PR.
  • src/config/sessions/paths.ts — the new fallback at line 159 in resolvePathWithinSessionsDir is security-sensitive path containment code

Last reviewed commit: 845c433

…tups

When OPENCLAW_STATE_DIR changes between session creation and resolution
(e.g., after reinstall or config change), absolute session file paths
pointing to other agents' sessions directories were rejected even though
they structurally match the valid .../agents/<agentId>/sessions/... pattern.

The existing fallback logic in resolvePathWithinSessionsDir extracts the
agent ID from the path and tries to resolve it via the current env's
state directory. When those directories differ, the containment check
fails. Now, if the path structurally matches the agent sessions pattern
(validated by extractAgentIdFromAbsoluteSessionPath), we accept it
directly as a final fallback.

Fixes openclaw#15410, Fixes openclaw#15565, Fixes openclaw#15468
@steipete steipete merged commit 3c3a39d into openclaw:main Feb 16, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment