Skip to content

Poisoned AgentSession index filenames can delete files outside AgentSessions #861

Description

@baron

Impact

A crafted or corrupted AgentSessionIndex.json entry can make normal conversation deletion remove a process-writable file outside the workspace's AgentSessions directory.

The metadata index is a derived cache, but its unvalidated filename field is currently used as destructive authority.

Affected snapshot

Confirmed statically on origin/main at a094dd9a83d03820201769ebc079c49fbd2e86fc.

Reachable scenario

  1. A current-schema index entry for a real compose tab contains filename: "../sentinel.json" (or another traversal path).
  2. The user deletes that tab/conversation through the ordinary Agent Mode UI.
  3. The service appends the index filename to AgentSessions, standardizes it, and passes the resulting outside path to durable deletion.
  4. If that path exists and is writable, it is removed.

A focused test can seed an index entry with the target tab ID and ../sentinel.json, invoke the normal batch-delete method, and assert that the sentinel survives.

Evidence

  • Index decoding accepts the persisted filename at Sources/RepoPrompt/Features/AgentMode/Runtime/AgentSessionMetadataIndex.swift:205-209.
  • Sources/RepoPrompt/Features/AgentMode/Runtime/AgentSessionDataService.swift:1378-1384 appends record.filename without requiring a canonical basename, direct child, or UUID match.
  • The candidate is standardized and deleted at AgentSessionDataService.swift:1407-1410,1424-1436.
  • The canonical session-file scan is already available in the same method, but the untrusted index candidate is added independently.
  • Existing deletion tests cover save/delete fencing, not poisoned index paths.

Expected behavior

Derived metadata must never authorize deletion. Session deletion should target only canonical direct-child session files whose decoded identity matches the requested session/tab.

Suggested direction

Prefer deletion candidates discovered by the canonical session-file scan. If the index remains an optimization, require a basename matching AgentSession-<UUID>.json, canonical direct-child containment, a matching decoded session ID/compose tab ID, and no symlink traversal before deletion.

Acceptance criteria

  • Traversal, absolute, nested, symlinked, and malformed index filenames cannot delete outside AgentSessions.
  • A mismatched filename/session/tab identity is ignored or reported as index corruption.
  • Valid indexed deletion remains functional.
  • Regression tests cover ../, absolute paths, symlink targets, and UUID mismatch.

Validation status

Static source review only; no user file was created or deleted.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:agent-modeAgent Mode runtime and interfacebugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions