Skip to content

fix: eliminate TOCTOU race in getOrCreateChatChannel - #847

Merged
jakharmonika364 merged 3 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-844-toctou-chat-channel
Aug 1, 2026
Merged

fix: eliminate TOCTOU race in getOrCreateChatChannel#847
jakharmonika364 merged 3 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-844-toctou-chat-channel

Conversation

@ionfwsrijan

Copy link
Copy Markdown
Contributor

Description

The getOrCreateChatChannel function in src/app/actions/chat.ts uses a classic check-then-insert pattern: first SELECT to see if a channel exists for (mentorId, menteeId), then INSERT if none found. Two concurrent requests can both read "no existing channel" and both insert, creating duplicate channels.

The schema already defines a uniqueIndex on (mentor_id, mentee_id), so the database would reject the second insert, but the application doesn't handle the conflict gracefully.

Changes

  • Inverted the order: INSERT first with .onConflictDoNothing(), then SELECT only on conflict (when the insert returns nothing)
  • This eliminates the TOCTOU window entirely — the database enforces uniqueness atomically
  • If the insert succeeds, the newly created channel is returned directly
  • If the insert conflicts (duplicate already exists), the existing channel is fetched and returned

Closes #844

The function had a classic check-then-insert pattern: first SELECT to
see if a channel exists, then INSERT if not found. Two concurrent
requests could both pass the SELECT and create duplicate channels.

The schema already defines a unique index on (mentor_id, mentee_id).
Fix: invert the order — try INSERT first with onConflictDoNothing(),
then SELECT only if the insert conflicts (duplicate). This eliminates
the TOCTOU window entirely by letting the database enforce uniqueness
atomically.

Closes Coder-s-OG-s#844
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@ionfwsrijan is attempting to deploy a commit to the codersogs-3057's projects Team on Vercel.

A member of the Team first needs to authorize it.

@ionfwsrijan

ionfwsrijan commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@jakharmonika364

Copy link
Copy Markdown
Collaborator

CI failure, please fix it

@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364 @Soumya-codr Please review now

@jakharmonika364 jakharmonika364 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Fix is correct - verified the unique index (chat_channels_mentor_mentee_uniq) already exists in schema, so onConflictDoNothing() has a real constraint to target, and the insert-first/select-on-conflict ordering genuinely closes the TOCTOU window rather than narrowing it.

One gap before merge: all three getOrCreateChatChannel tests either error out early or exercise the conflict-fallback branch - none covers the primary case, a fresh insert that succeeds with no conflict. That's the path every non-duplicate call takes and it's untested through the new .onConflictDoNothing().returning() chain. Can you add a test asserting newChannel truthy -> immediate ok({ channelId }) return?

@jakharmonika364 jakharmonika364 added Needs author reply Author need to reply and removed CI CD pending labels Jul 31, 2026
Adds the missing primary-case test (insert succeeds, immediate ok({ channelId })
return, no conflict fallback select). Also mocks the insert chain in the
conflict-fallback test, which previously hit a TypeError on undefined values.
@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364 Please review now. I've made the changes

@jakharmonika364 jakharmonika364 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@jakharmonika364 jakharmonika364 added level:advanced Advanced level difficulty quality:clean Clean, well-structured contribution type:bug Bug fix gssoc:approved Approved by GSSOC admin SSoC26 Hard ECSoC26 ECSoC26-L2 Medium good-pr and removed Needs author reply Author need to reply labels Aug 1, 2026
@jakharmonika364
jakharmonika364 merged commit 34879c6 into Coder-s-OG-s:main Aug 1, 2026
2 of 3 checks passed
@ecsoc-sentinel ecsoc-sentinel Bot added ECSoC26-L2 Medium and removed ECSoC26-L2 Medium labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ECSoC26-L2 Medium ECSoC26 good-pr gssoc:approved Approved by GSSOC admin Hard level:advanced Advanced level difficulty quality:clean Clean, well-structured contribution SSoC26 type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] TOCTOU Race in getOrCreateChatChannel Allows Duplicate Channel Creation

2 participants