RocketChat / RocketChat/Rocket.Chat

saveUserIdentity coerces missing username/name to literal "undefined", corrupting VideoConference and CallHistory user references

Open
#39,205 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: bug
Dominant language
TypeScript
Stars
46.1k
Forks
13.9k
Avg merge
3d 3h
Merged PRs (30d)
130

Description

Description:

When saveUserIdentity receives a partial update (for example, only name), it still coerces optional fields with String(rawName).trim() / String(rawUsername).trim().
If one field is omitted, that omitted field can become the literal string "undefined" in internal variables.

Because change detection is computed from these coerced values, usernameChanged/nameChanged can be incorrectly true even when a field was not provided. Later reference updates use those values and can persist "undefined" into user reference fields in video_conference and call_history.

Steps to reproduce:
  1. Create a user with existing call/video references (e.g., make at least one media call/video conference so entries exist in call_history / video_conference).
  2. Call POST /api/v1/users.updateOwnBasicInfo with only name in data (omit username), for example:
    {
    "data": {
    "name": "New Display Name"
    }
    }
  3. Check updated references in video_conference and/or call_history for that user.
Expected behavior:

Only provided fields should be treated as changed.
A name-only update must not alter username references, and no reference field should ever be written as literal "undefined".

Actual behavior:

Omitted optional fields are coerced to string "undefined", and downstream reference updates can write "undefined" into persisted username/name reference fields in video_conference and call_history.

Server Setup Information:
  • Version of Rocket.Chat Server: develop (source-level verification)
  • License Type: N/A
  • Number of Users: N/A
  • Operating System: N/A
  • Deployment Method: N/A
  • Number of Running Instances: N/A
  • DB Replicaset Oplog: N/A
  • NodeJS Version: N/A
  • MongoDB Version: N/A
Client Setup Information
  • Desktop App or Browser Version: N/A (API reproduction)
  • Operating System: N/A
Additional context

Relevant code paths:

  • apps/meteor/app/lib/server/functions/saveUserIdentity.ts

    • String(rawName).trim() / String(rawUsername).trim()
    • nameChanged / usernameChanged computed from coerced values
    • reference writes in VideoConference.updateUserReferences and CallHistory.updateUserReferences
  • packages/rest-typings/src/v1/users/UsersUpdateOwnBasicInfoParamsPOST.ts

    • name and username are independently optional
    • apps/meteor/server/methods/saveUserProfile.ts
    • still calls saveUserIdentity for partial identity updates
Relevant logs:

No server exception is required for this bug; it is a data integrity issue caused by incorrect field coercion/change detection logic.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with apps/meteor/app/lib/server/functions/saveUserIdentity.ts, then trace the partial-update call from apps/meteor/server/methods/saveUserProfile.ts and the optional fields in UsersUpdateOwnBasicInfoParamsPOST.ts. Reproduce the name-only POST request and inspect VideoConference.updateUserReferences and CallHistory.updateUserReferences; done means omitted fields are not treated as changed and references contain no literal "undefined".

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend, databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.