#15176: fix(sessions): allow channel-routed session IDs and cross-agent paths
stale
size: S
Cluster:
Session Management Enhancements
## Summary
Session path hardening in 2026.2.12 breaks all messaging channels (iMessage, WhatsApp, Telegram, Discord) in multi-agent setups. Two regressions:
1. `SAFE_SESSION_ID_RE` rejects `:`, `+`, `@` — characters used in every channel session key (E.164 phone numbers, email handles, colon separators)
2. `resolvePathWithinSessionsDir` rejects absolute paths stored by older versions when the handler resolves a different agent's sessions directory than where the file lives (channel bindings route to agent "knox" but handler resolves "default")
lobster-biscuit
## Behavior Changes
- `SAFE_SESSION_ID_RE` now allows `:`, `+`, `@` and session IDs up to 255 chars (was 128). Path traversal characters (`/`, `\`, `..`) still blocked.
- `resolvePathWithinSessionsDir` accepts absolute paths within the parent `agents/` directory, not just the specific agent's `sessions/` dir. Paths outside the agents root are still rejected.
## Reproduction
```
# Multi-agent setup with channel binding routing iMessage to agent "knox"
# Session created under agents/knox/sessions/uuid.jsonl
# Handler resolves sessionsDir for agent "default"
# → relative path becomes ../../knox/sessions/uuid.jsonl → REJECTED
```
Error in gateway logs:
```
[imessage] handler failed: Error: Session file path must be within sessions directory
```
## Tests
- `pnpm build` — pass
- `pnpm check` (format + types + lint) — pass
- `pnpm test` — 279/279 pass
New test cases added:
- Session IDs with `:`, `+`, `@` pass validation
- Cross-agent absolute paths within agents root accepted
- Absolute paths outside agents root still rejected
- All existing path traversal attack tests still pass
## Evidence
Gateway error log showing every inbound iMessage rejected:
```
2026-02-13T03:15:23.992Z [imessage] handler failed: Error: Session file path must be within sessions directory
2026-02-13T03:22:37.357Z [imessage] handler failed: Error: Session file path must be within sessions directory
2026-02-13T03:28:34.057Z [imessage] handler failed: Error: Session file path must be within sessions directory
2026-02-13T03:36:49.844Z [imessage] handler failed: Error: Session file path must be within sessions directory
```
Session store showing absolute path stored by pre-2026.2.12:
```json
{
"agent:knox:imessage:direct:+17189153805": {
"sessionFile": "/Users/knox/.openclaw/agents/knox/sessions/2a6beef3-efaa-4b6b-bcfb-9dd76908de23.jsonl"
}
}
```
Fixes #15140, #15141, #15152, #15155, #15161
**Sign-Off**
- Models used: Claude Opus 4.6
- Submitter effort: ~1 hour debugging + root cause analysis + fix + tests
- Agent notes: Root cause identified by tracing gateway error logs → session store entries → path.relative() mismatch between bound agent (knox) and resolved agent (default). Fix verified against real session store data.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR relaxes session ID validation to support channel-routed keys (allowing `:`, `+`, `@` and longer IDs) and updates session transcript path resolution to accept certain absolute paths to fix multi-agent binding regressions.
Main correctness concern: the new absolute-path fallback expands the trusted boundary from a specific agent’s `sessions/` directory to the entire `<state>/agents/` tree. Because the resolved path is subsequently used for filesystem reads, this can allow a corrupted/poisoned session store to redirect reads to non-session files under `agents/` (not just `agents/*/sessions/`). Tightening the allowlist to only `agents/*/sessions/**` would preserve the intended regression fix without broadening access.
<h3>Confidence Score: 3/5</h3>
- This PR is close to safe to merge but currently broadens session file path acceptance more than necessary.
- The regression fix is well-targeted and covered by tests, but the new absolute-path fallback in `resolvePathWithinSessionsDir` permits any path under `<state>/agents/**`, which is a wider trust boundary than “cross-agent sessions” and can enable unintended file reads if session store entries are corrupted or attacker-controlled.
- src/config/sessions/paths.ts
<sub>Last reviewed commit: 4021ea8</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#16249: fix(sessions): allow cross-agent session paths in multi-agent bindings
by 0xbrak · 2026-02-14
87.3%
#15744: fix: allow cross-agent session path validation
by scottgl9 · 2026-02-13
87.3%
#15793: fix(sessions): gracefully handle stale cross-agent session file paths
by lxcong · 2026-02-13
85.4%
#16171: fix: trust absolute sessionFile paths in multi-agent setups [AI-ass...
by iJaack · 2026-02-14
84.9%
#16061: fix(sessions): tolerate invalid sessionFile metadata
by haoyifan · 2026-02-14
84.6%
#15941: fix(sessions): allow session file paths from other agents' sessions...
by LiJianLi128 · 2026-02-14
84.3%
#15888: fix: store relative session file paths instead of absolute
by devAnon89 · 2026-02-14
84.3%
#20336: fix(sessions): resolve transcriptPath using agentId when storePath ...
by Limitless2023 · 2026-02-18
83.8%
#15982: fix: pass agentId to resolveSessionFilePath in reply flow (NX-003)
by automagik-genie · 2026-02-14
82.8%
#17132: fix: filter out invalid session entries with empty sessionFile
by Limitless2023 · 2026-02-15
82.2%