google-gemini / google-gemini/gemini-cli
Path traversal in checkpoint delete/load: a ../ tag deletes files outside the checkpoints directory (legacy raw path)
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## Summary
`/chat delete ` (and checkpoint load) resolve the legacy fallback path from the RAW tag, so a tag containing `../` deletes/reads a `.json` file OUTSIDE the checkpoint directory. Verified against real code with an isolated sandbox:
- tag `x/../../secret` → `deleteCheckpoint` unlinked `/.json`-style path outside the checkpoints dir and returned `true`
- root cause: `deleteCheckpoint` and `_getCheckpointPath` build `oldPath = path.join(geminiDir, 'checkpoint-' + tag + '.json')` with the raw tag; `path.join` normalizes the `..` away. The new encoded path (`_checkpointPath`) is safe — only the legacy raw fallback is exposed.
- the tag comes straight from `args.trim()` in the chat command with no validation, and `deleteCheckpoint` is also reachable programmatically.
This is the same bug class as #28699 (which fixed it for the a2a-server restore path with a basename guard) — the core logger delete/load paths were left raw.
## Expected
Contain the legacy fallback: only touch the raw path when it resolves inside the checkpoints dir (same basename-style guard as #28699), so traversal tags simply miss instead of deleting outside files. Legit flat tags behave exactly as before.
Contributor guide
Research direction
Locate deleteCheckpoint and _getCheckpointPath, then trace the chat command’s args.trim() input and compare the legacy fallback handling with the basename guard from #28699. Verify that traversal tags cannot reach files outside the checkpoints directory while legitimate flat tags continue to work for delete and load.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100