fix: resolve symlinks in session path validation (#18553)#18593
fix: resolve symlinks in session path validation (#18553)#18593EpaL wants to merge 1 commit intoopenclaw:mainfrom
Conversation
…h-escape errors When the OpenClaw state directory is accessed through a symlink (e.g. ~/.clawdbot -> ~/.openclaw after a rename/migration), session file paths stored with the old symlink prefix fail the containment check in resolvePathWithinSessionsDir because path.relative() does not follow symlinks. This causes: - `doctor --fix` to crash after applying config migrations - Discord guild message handler to crash on every inbound message - Any code path that resolves stored sessionFile paths to fail Fix: use fs.realpathSync() to resolve symlinks on both the base sessions directory and the candidate path before computing the relative path. Falls back gracefully if the path does not exist yet. Fixes openclaw#18553
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc68137e47
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const realBase = safeRealpathSync(resolvedBase) ?? resolvedBase; | ||
| const realTrimmed = path.isAbsolute(trimmed) ? (safeRealpathSync(trimmed) ?? trimmed) : trimmed; | ||
| const normalized = path.isAbsolute(realTrimmed) ? path.relative(realBase, realTrimmed) : realTrimmed; |
There was a problem hiding this comment.
Handle missing symlinked transcripts without false escape
When sessionsDir is a symlink path (for example .clawdbot/.../sessions) and sessionFile is an absolute path under that same alias but the file does not exist yet (or was deleted), safeRealpathSync(trimmed) falls back to the unresolved symlink path while realBase is canonicalized to the target path. In this mixed form, path.relative(realBase, realTrimmed) incorrectly starts with .., so resolvePathWithinSessionsDir throws Session file path must be within sessions directory for a path that is actually inside the same sessions tree. This introduces crashes/failures on code paths that should tolerate missing transcripts (e.g. integrity checks or transcript recreation).
Useful? React with 👍 / 👎.
|
Greptile encountered an error while reviewing this PR. Please reach out to support@greptile.com for assistance. |
|
This pull request has been automatically marked as stale due to inactivity. |
|
Deep-dive merge-readiness pass: The symlink realpath direction looks correct and should stay. Before merge, please restore/retain the previously shipped structural fallback for state-dir drift (the behavior added to handle changed
Current Changelog guidance if merged: one |
|
Merge checklist (must-have):
Changelog line (if merged): Credit note: |
|
Thanks for driving this symlink path edge case. Closing as superseded by #24657, which ships the symlink-safe session path validation plus regression coverage. If there is still an uncovered case, share it and we can reopen immediately. |
Problem
When the OpenClaw state directory is accessed through a symlink (e.g.
~/.clawdbot -> ~/.openclawafter the rename migration), session file paths stored with the old symlink prefix fail the containment check inresolvePathWithinSessionsDir.path.relative()does not follow symlinks, so a stored path like:computed relative to:
produces
../../../../.clawdbot/agents/main/sessions/abc.jsonl(starts with..), which fails validation even though both paths resolve to the same physical file.Impact
doctor --fixcrashes after applying config migrationssessionFilepaths failsRoot cause
The
.clawdbot→.openclawmigration left a compatibility symlink, butresolvePathWithinSessionsDirandresolvePathFromAgentSessionsDirusepath.resolve()which does not follow symlinks.Fix
Use
fs.realpathSync()to resolve symlinks on both the base sessions directory and the candidate path before computing the relative path. A newsafeRealpathSync()helper falls back gracefully if the path does not exist yet.Testing
.clawdbot -> .openclawsymlinkdoctor --fixcompletes without errorFixes #18553
Greptile Summary
This PR fixes session path validation failures caused by symlinks (e.g.,
~/.clawdbot → ~/.openclaw) by usingfs.realpathSyncto resolve symlinks on both the base directory and candidate paths before computing relative paths. A newsafeRealpathSynchelper gracefully falls back when paths don't exist yet. The fix is applied consistently in bothresolvePathFromAgentSessionsDirandresolvePathWithinSessionsDir.path.relative()is the correct approach.return path.resolve(trimmed)) that was explicitly added in commit90774c09to handle a different scenario — whenOPENCLAW_STATE_DIRchanges between session creation and resolution (no symlinks involved). This could re-introduce the issues fixed by that earlier commit ([Bug]: Multi-agent setup: "Session file path must be within sessions directory" error #15410, [Bug]: Multi-agent Telegram: "Session file path must be within sessions directory" after 2026.2.12 update #15565, Bug Report: Session file path must be within sessions directory — All non-default agents fail to respond #15468).Confidence Score: 3/5
src/config/sessions/paths.ts— specifically the removed structural fallback inresolvePathWithinSessionsDiraround lines 164-170.Last reviewed commit: fc68137
(2/5) Greptile learns from your feedback when you react with thumbs up/down!