Skip to content

fix(chat-history): only delete message file for owned sessions - #2043

Merged
openai0229 merged 5 commits into
OtterMind:mainfrom
Aias00:fix/2034-chat-history-idor
Jul 24, 2026
Merged

openai0229 merged 5 commits into
OtterMind:mainfrom
Aias00:fix/2034-chat-history-idor

Conversation

@Aias00

@Aias00 Aias00 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Related issue

Closes #2034

Summary

AiChatHistoryServiceImpl.deleteSessionLocal called sessions.removeIf(s -> Objects.equals(s.getId(), sessionId)) against the current user's session list — a no-op if the session does not belong to this user — then unconditionally Files.deleteIfExists(messagesPath(sessionId)) where messagesPath is baseDir.resolve(sessionId + ".json"). A user could therefore delete another user's chat message file by supplying that session's id, regardless of ownership. Now the message file is deleted only when removeIf actually removed the session (i.e. it was owned by the requesting user).

Affected surfaces

  • Frontend / Web
  • Backend / API / Storage
  • Database plugin / Driver
  • JCEF / Desktop packaging
  • CI / Build / Release
  • Documentation only

Verification

  • Commands and results: mvn -B -q -f chat2db-community-server/pom.xml -pl chat2db-community-domain/chat2db-community-domain-core -am -Dmaven.test.skip=true compile -> BUILD SUCCESS.
  • Manual verification: List.removeIf returns true iff the list changed (a session with that id belonged to the user); when it returns false, the method returns without touching the filesystem. The owned path is unchanged.
  • UI evidence: N/A

Risk and compatibility

  • Public API or stored data: Behavior change — a delete request for a session the user does not own now no longer deletes the file (previously it did). This is the intended authorization fix.
  • Database or driver compatibility: N/A.
  • Network, privacy, or security: Fixes an IDOR allowing deletion of another user's chat history file by session id.
  • Community / Local / Pro boundary: N/A.
  • Backward compatibility: Legitimate delete of an owned session is unchanged.

Reviewer map

  • Start here: AiChatHistoryServiceImpl.deleteSessionLocal — capture boolean removed = sessions.removeIf(...) and if (!removed) return; before deleting the message file.
  • Failure condition: A user can still delete another user's sessionId.json by supplying that id.
  • Rollback or disable path: Revert this single commit.

Contributor declaration

  • I linked the Issue that defines this change.
  • I tested the affected behavior and reported the actual results above.
  • I did not include credentials, private data, or generated build output.
  • I disclosed substantial AI assistance below, or this PR contains no substantial AI-generated code.

AI assistance: The fix, verification, and PR description were produced with Claude Code assistance.

deleteSessionLocal removed the session from the user's list (no-op if
not owned) but then unconditionally Files.deleteIfExists the message
file, so a caller could delete another user's file by session id. Only
delete when removeIf actually removed an owned session.

Fixes OtterMind#2034

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 24, 2026 09:14
@Aias00
Aias00 requested a review from openai0229 as a code owner July 24, 2026 09:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@openai0229 openai0229 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the ownership guard and added a focused regression test covering non-owner and owner deletion behavior. The security issue is addressed and the test passes locally.

@openai0229

Copy link
Copy Markdown
Contributor

Maintainer follow-up: I added a focused regression test on the contributor branch. It creates an owner session and message, verifies a different user cannot delete the message file or session data, then verifies the owner can delete it. Local verification: mvn -B -q -f chat2db-community-server/pom.xml -pl chat2db-community-domain/chat2db-community-domain-core -am -Dtest=AiChatHistoryServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test passed.

@openai0229

Copy link
Copy Markdown
Contributor

Additional maintainer review found the same ownership gap on the write path: the HTTP adapter supplies the authenticated user ID, but accepts a client-provided session ID, and addMessageLocal previously appended to sessionId.json without checking that the session belonged to that user. I added an ownership check shared with reads plus a regression test proving a non-owner cannot append to another user's message file. The focused test suite now covers Spring constructor selection, non-owner deletion, owner deletion, and non-owner writes; it passes locally.

@openai0229 openai0229 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final review after maintainer hardening and current-main CI. Session ownership is now enforced for reads, writes, and deletion; focused tests cover non-owner write/delete behavior, owner deletion, and Spring constructor selection. All checks, including Java CodeQL, passed.

@openai0229
openai0229 merged commit 42e21e6 into OtterMind:main Jul 24, 2026
17 checks passed
@openai0229 openai0229 moved this from In Review to Done in Chat2DB Community Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

AI chat history deleteSessionLocal deletes another user's message file (IDOR)

3 participants