Skip to content

fix: block verification field updates in profile endpoint#271

Merged
yash-pouranik merged 3 commits into
geturbackend:mainfrom
VarshithReddy2006:fix/updateprofile-verification-fields
Jun 6, 2026
Merged

fix: block verification field updates in profile endpoint#271
yash-pouranik merged 3 commits into
geturbackend:mainfrom
VarshithReddy2006:fix/updateprofile-verification-fields

Conversation

@VarshithReddy2006
Copy link
Copy Markdown
Contributor

@VarshithReddy2006 VarshithReddy2006 commented Jun 5, 2026

🚀 Pull Request Description

Fixes #269

🛠️ Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)

Summary

This PR prevents verification-related account state fields from being modified through the generic updateProfile endpoint.

Root Cause

The updateProfile() controller removed sensitive fields such as password, email, and _id before processing updates, but verification-related fields (emailVerified, isVerified, and isverified) were not restricted.

As a result, authenticated users could include these fields in profile update requests and potentially modify verification state outside the intended verification workflow.

Changes Made

  • Added explicit removal of:

    • emailVerified
    • isVerified
    • isverified
  • Preserved the existing profile update flow.

  • Kept existing sanitization and validation behavior unchanged.

🧪 Testing & Validation

Backend Verification:

  • Verified the fix through code-path analysis.
  • Confirmed verification fields are removed before database updates.
  • Confirmed existing profile update functionality remains unchanged.
  • New unit tests added (no existing updateProfile-specific tests found).

Frontend Verification:

  • Not applicable (backend-only change).

📸 Screenshots / Recordings

Not applicable.

✅ Checklist

  • My code follows the code style of this project.
  • I have performed a self-review of my code.
  • My changes generate no new warnings or errors.
  • I have not introduced breaking changes.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue in the profile update endpoint that allowed verification-status fields to be modified via API requests. Users can no longer change account verification state through profile edits.
    • The update process now only accepts allowed profile fields from request payloads, reducing accidental or unauthorized changes to account attributes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Linter diff in the way? Review this PR in Change Stack to focus on meaningful changes and expand context only when needed.

Review Change Stack

Warning

Review limit reached

@VarshithReddy2006, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 1 second. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3081291a-2f91-4f33-82ee-03ef649a45a5

📥 Commits

Reviewing files that changed from the base of the PR and between 23e584c and b8054a4.

📒 Files selected for processing (1)
  • apps/public-api/src/controllers/userAuth.controller.js
📝 Walkthrough

Walkthrough

updateProfile now computes allowedFields from the users collection model, excludes verification-related keys (emailVerified, isVerified, isverified), and constructs updateData by copying only allowed keys from req.body before persisting.

Changes

Verification Field Protection

Layer / File(s) Summary
Schema-derived whitelist for profile updates
apps/public-api/src/controllers/userAuth.controller.js
updateProfile computes allowedFields from usersColConfig.model, excludes verification fields, and builds updateData only from permitted keys found in req.body, replacing the previous copy-then-delete approach.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I’m a rabbit in the code-lined glen,
I hop through payloads now and then,
I pick the keys that rightly stay,
Toss falsehoods, keep the bad away,
Verification’s safe — hooray! 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: block verification field updates in profile endpoint' accurately describes the main change: preventing verification fields from being updated through the profile endpoint.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #269 by blocking verification field updates; it uses an allowlist approach for permitted fields, validates against the user schema, and includes unit tests to prevent regressions.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the verification field update vulnerability in the updateProfile endpoint; no out-of-scope modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@VarshithReddy2006
Copy link
Copy Markdown
Contributor Author

Hi @yash-pouranik,

This PR addresses Issue #269 by preventing verification-related account state fields from being updated through the generic profile update endpoint.

The fix explicitly removes emailVerified, isVerified, and isverified from the update payload before processing, ensuring verification status can only be modified through the intended verification workflow.

Looking forward to your review. Thank you!

@yash-pouranik
Copy link
Copy Markdown
Collaborator

yash-pouranik commented Jun 5, 2026

does this PR requires any changes?
@coderabbitai

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff
gh pr view 271 --repo geturbackend/urBackend --json files,body,title

# Get the diff of the changed files
gh pr diff 271 --repo geturbackend/urBackend

Length of output: 3471



@yash-pouranik The core fix in this PR is correct and directly addresses issue #269. However, there are a few things worth considering before merging:


✅ What's good

  • The three verification fields (emailVerified, isVerified, isverified) are correctly stripped before the DB update.
  • Existing behavior and sanitization are preserved.

⚠️ Suggested improvements

  1. Denylist is fragile — consider an allowlist approach
    The current pattern explicitly deletes disallowed fields. If new sensitive fields are added to the user schema in the future (e.g., role, isAdmin, isActive, isBlocked), they would need to be remembered and manually added here. A safer approach is to define an explicit allowlist of fields that can be updated:

    const ALLOWED_UPDATE_FIELDS = ['username', 'firstName', 'lastName', 'bio', /* ... */];
    const updateData = {};
    for (const key of ALLOWED_UPDATE_FIELDS) {
      if (req.body[key] !== undefined) updateData[key] = req.body[key];
    }

    This way, new fields are opt-in rather than opt-out for the update endpoint.

  2. Other potentially sensitive fields not blocked
    Fields like role, isAdmin, isActive, isBlocked, createdAt, __v are not explicitly removed and could be submitted in a profile update request. It's worth auditing the full user schema to ensure all security-sensitive fields are protected.

  3. No unit tests
    The PR itself notes no tests were added. For a security fix, even a simple test asserting that isVerified cannot be changed via the profile update endpoint would add meaningful protection against regressions.


Summary

The PR works as intended for the specific issue, but the allowlist approach would make it significantly more robust and maintainable long-term. At minimum, a quick audit of the full user schema for other sensitive fields is recommended.

@yash-pouranik
Copy link
Copy Markdown
Collaborator

Please follow this approach
@VarshithReddy2006

@VarshithReddy2006
Copy link
Copy Markdown
Contributor Author

Thank you for the review @yash-pouranik.

That's a good point regarding the denylist approach. I'll review the user schema and update the implementation to use an allowlist of profile fields that can be modified through the endpoint, which will provide better long-term protection for newly added sensitive fields.

I'll push an updated revision shortly.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/public-api/src/controllers/userAuth.controller.js (1)

1531-1571: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Duplicate usersColConfig declaration causes syntax error.

The pipeline failure indicates: SyntaxError: Identifier 'usersColConfig' has already been declared at line 1570. The new allowlist code correctly declares usersColConfig at line 1531, but the original declaration at line 1570 was not removed, causing a duplicate const in the same scope.

🐛 Proposed fix: Remove the duplicate declaration
         if (req.body[field] !== undefined) {
             updateData[field] = req.body[field];
         }
     }

     if (updateData.username !== undefined) {
         const username = updateData.username;
         if (typeof username !== 'string' || username.length < 3 || username.length > 50) {
             return res.status(400).json({ error: "Username must be between 3 and 50 characters." });
         }
     }

     const sanitizedUpdateData = sanitize(updateData);

-    const usersColConfig = project.collections.find(c => c.name === 'users');
-    if (!usersColConfig) return res.status(404).json({ error: "Auth collection not found" });

     const connection = await getConnection(project._id);
     const Model = getCompiledModel(connection, usersColConfig, project._id, project.resources.db.isExternal);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/public-api/src/controllers/userAuth.controller.js` around lines 1531 -
1571, The duplicate declaration of usersColConfig causes a SyntaxError; remove
the second const usersColConfig = project.collections.find(c => c.name ===
'users') and reuse the earlier usersColConfig variable instead, keeping the
existence check (if (!usersColConfig) return res.status(404)... ) and the
subsequent logic (allowedFields, updateData, sanitize) intact so no
redeclaration occurs in the same scope.

Source: Pipeline failures

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/public-api/src/controllers/userAuth.controller.js`:
- Around line 1531-1571: The duplicate declaration of usersColConfig causes a
SyntaxError; remove the second const usersColConfig = project.collections.find(c
=> c.name === 'users') and reuse the earlier usersColConfig variable instead,
keeping the existence check (if (!usersColConfig) return res.status(404)... )
and the subsequent logic (allowedFields, updateData, sanitize) intact so no
redeclaration occurs in the same scope.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ba60167-8c5c-462d-ba27-5c65b018de40

📥 Commits

Reviewing files that changed from the base of the PR and between 91445d8 and 23e584c.

📒 Files selected for processing (1)
  • apps/public-api/src/controllers/userAuth.controller.js

@VarshithReddy2006
Copy link
Copy Markdown
Contributor Author

Hi @yash-pouranik,

I've updated the implementation to follow the allowlist approach as requested.

Changes made:

  • Replaced the denylist-based field removal logic with a schema-driven allowlist.
  • Allowed fields are now derived from the configured user schema while excluding sensitive fields (_id, password, email, emailVerified, isVerified, isverified).
  • Preserved the existing username validation, sanitization flow, and runValidators: true.

I also ran the public-api test suite locally after the update:

  • Test Suites: 13 passed, 13 total
  • Tests: 147 passed, 147 total

Kindly review the updated changes. Thank you!

@yash-pouranik
Copy link
Copy Markdown
Collaborator

@Nitin-kumar-yadav1307
Check
LGTM

@yash-pouranik yash-pouranik merged commit 23c590b into geturbackend:main Jun 6, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: updateProfile Bypasses User Schema Validation and Permits Verification-State Updates

2 participants