Skip to content

fix(auth): sanitize login response to exclude password hash#365

Closed
adityack477 wants to merge 2 commits into
GitMetricsLab:mainfrom
adityack477:fix/limit-login-response
Closed

fix(auth): sanitize login response to exclude password hash#365
adityack477 wants to merge 2 commits into
GitMetricsLab:mainfrom
adityack477:fix/limit-login-response

Conversation

@adityack477
Copy link
Copy Markdown
Contributor

@adityack477 adityack477 commented May 21, 2026

Related Issue


Description

Added toSafeObject() method on User model that returns only id,
username, and email. Use it in the /api/auth/login route instead
of sending the raw Mongoose user object which included the
bcrypt-hashed password field.


How Has This Been Tested?

Tested with

curl -X POST http://localhost:<PORT>/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"Test1234"}'

Screenshots (if applicable)


Type of Change

  • Bug fix
  • New feature
  • Code style update
  • Breaking change
  • Documentation update

Summary by CodeRabbit

  • Bug Fixes
    • Updated login endpoint to return sanitized user data without exposing sensitive fields.

Review Change Stack

@netlify
Copy link
Copy Markdown

netlify Bot commented May 21, 2026

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit 3f601cf
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a0f27df462a8d00081b6b9b
😎 Deploy Preview https://deploy-preview-365--github-spy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Warning

Rate limit exceeded

@adityack477 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 54 minutes and 50 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 212d4d69-c281-489c-90ac-b5e12359666b

📥 Commits

Reviewing files that changed from the base of the PR and between ed8308b and 3f601cf.

📒 Files selected for processing (1)
  • backend/routes/auth.js
📝 Walkthrough

Walkthrough

A security fix introduces UserSchema.methods.toSafeObject() to return only id, username, and email, then updates the login endpoint to use this method instead of exposing the raw user object with its password hash.

Changes

User Data Sanitization for Auth Responses

Layer / File(s) Summary
Safe user serialization contract and login response integration
backend/models/User.js, backend/routes/auth.js
UserSchema.methods.toSafeObject() returns sanitized user data with only identifier and profile fields. The login endpoint response now calls req.user.toSafeObject() instead of returning the raw user object.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A password hash hid from the view,
With toSafeObject, now safe and true,
The login route sends fields so light,
No secrets leaked—security done right! 🔒

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately describes the main change: sanitizing the login response to exclude the password hash by returning only safe user fields.
Description check ✅ Passed The pull request description follows the template structure with Related Issue, Description, and How Has This Been Tested sections filled out. Type of Change is marked correctly as Bug fix.
Linked Issues check ✅ Passed The pull request successfully addresses issue #364 by implementing toSafeObject() method to sanitize the login response and prevent password hash leakage in the /api/auth/login endpoint.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #364: adding the toSafeObject() method and using it in the login route to sanitize the response. No unrelated 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.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

🎉 Thank you @adityack477 for your contribution. Please make sure your PR follows https://github.com/GitMetricsLab/github_tracker/blob/main/CONTRIBUTING.md#-pull-request-guidelines

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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
backend/routes/auth.js (1)

34-36: 💤 Low value

Guard against req.user being undefined.

If passport.authenticate('local') is ever configured (now or in the future) with { failWithError: false } semantics that allow the handler to run without a user, calling req.user.toSafeObject() will throw a TypeError. A small defensive check makes the handler more robust and avoids leaking a 500 on edge cases.

♻️ Optional hardening
-    + res.status(200).json({ message: 'Login successful', user: req.user.toSafeObject() });
+    if (!req.user) {
+        return res.status(401).json({ message: 'Authentication failed' });
+    }
+    res.status(200).json({ message: 'Login successful', user: req.user.toSafeObject() });
🤖 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 `@backend/routes/auth.js` around lines 34 - 36, The login route handler
currently assumes req.user exists and calls req.user.toSafeObject(), which can
throw if authentication passed control without a user; update the
router.post("/login", validateRequest(loginSchema),
passport.authenticate('local'), (req, res) => {...}) handler to defensively
check for req.user before calling toSafeObject() — if req.user is missing,
return a 401/appropriate error JSON (or an object with user: null) and otherwise
call req.user.toSafeObject() and return the safe user in the 200 response.
backend/models/User.js (1)

34-40: 💤 Low value

Consider using the id virtual (string) for consistency.

this._id is a Mongoose ObjectId instance. It serializes to a hex string via JSON.stringify, but consumers reading the property programmatically (before serialization) get an ObjectId, which can cause subtle bugs in strict comparisons. The Mongoose id virtual returns the string form directly.

♻️ Optional refactor
 UserSchema.methods.toSafeObject = function () {
   return {
-    id: this._id,
+    id: this.id,
     username: this.username,
     email: this.email,
   };
 };
🤖 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 `@backend/models/User.js` around lines 34 - 40, In
UserSchema.methods.toSafeObject, replace use of the raw ObjectId this._id with
the Mongoose string virtual this.id so the returned id is a JS string; update
the toSafeObject method (referencing UserSchema and toSafeObject) to return id:
this.id instead of id: this._id and keep username and email unchanged to avoid
subtle type/comparison bugs.
🤖 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.

Inline comments:
In `@backend/routes/auth.js`:
- Line 35: The line currently has a stray '+' character before the response call
causing a unary plus to be applied to res.status(...).json(...); remove the
leading '+' so the statement is simply res.status(200).json({ message: 'Login
successful', user: req.user.toSafeObject() });, ensure req.user.toSafeObject()
remains unchanged, then run the linter/tests to confirm the unary plus is gone
and the response behaves normally.

---

Nitpick comments:
In `@backend/models/User.js`:
- Around line 34-40: In UserSchema.methods.toSafeObject, replace use of the raw
ObjectId this._id with the Mongoose string virtual this.id so the returned id is
a JS string; update the toSafeObject method (referencing UserSchema and
toSafeObject) to return id: this.id instead of id: this._id and keep username
and email unchanged to avoid subtle type/comparison bugs.

In `@backend/routes/auth.js`:
- Around line 34-36: The login route handler currently assumes req.user exists
and calls req.user.toSafeObject(), which can throw if authentication passed
control without a user; update the router.post("/login",
validateRequest(loginSchema), passport.authenticate('local'), (req, res) =>
{...}) handler to defensively check for req.user before calling toSafeObject() —
if req.user is missing, return a 401/appropriate error JSON (or an object with
user: null) and otherwise call req.user.toSafeObject() and return the safe user
in the 200 response.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5fd9b437-9ec1-440c-9d24-ce72e5d49544

📥 Commits

Reviewing files that changed from the base of the PR and between 9d34c19 and ed8308b.

📒 Files selected for processing (2)
  • backend/models/User.js
  • backend/routes/auth.js

Comment thread backend/routes/auth.js Outdated
@adityack477
Copy link
Copy Markdown
Contributor Author

@mehul-m-prajapati please review and /merge

@mehul-m-prajapati
Copy link
Copy Markdown
Collaborator

not required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: Sanitize and limit login response - avoid leaking password hash in /api/auth/login

2 participants