Phase 1: Critical Security Refactors #31
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Phase 1: Critical Security Refactors
Summary
This PR implements Phase 1 of the comprehensive security refactoring plan for nodejs-goof, addressing critical security vulnerabilities while maintaining application functionality. The changes include:
/account_detailsendpoint via strict field allowlisting_.merge()with explicit property copyingDependency Updates
lodash: 4.17.4 → 4.17.21 (fixes prototype pollution, command injection)ejs: 1.0.0 → 3.1.10 (fixes RCE, XSS, DoS vulnerabilities)marked: 0.3.5 → 12.0.2 (fixes XSS)mongoose: 4.2.4 → 6.12.3 (fixes buffer memory exposure, maintains callback compatibility)validator: 13.5.2 → 13.11.0 (latest version with security fixes)express-fileupload: 0.0.5 → 1.5.0 (fixes DoS, prototype pollution)adm-zip: 0.5.2 → 0.5.16 (latest with Zip Slip fixes)Note on Mongoose: Upgraded to 6.12.3 instead of 8.x because Mongoose 8 removed callback support, which would require extensive code refactoring beyond Phase 1 scope. Version 6.12.3 includes all critical security fixes while maintaining backward compatibility.
Code Security Fixes
routes/index.js:
adminLoginSuccess(): ValidatesredirectPageonly accepts local URLs (/prefix, not//)save_account_details(): Implements strict allowlisting of 5 expected fields, adds 1000-char length limits, removes ReDoS-vulnerableallow_display_nameoption andvalidator.rtrim()chat.add(): Replaces unsafe_.merge()with explicit property copying usingObject.create(null)and field allowlistingviews/admin.ejs:
<%- redirectPage %>to<%= redirectPage %>to properly escape output and prevent XSSReview & Testing Checklist for Human
Test all modified endpoints manually - I verified the app starts successfully, but did NOT manually test the specific endpoints that were changed:
/account_detailswith various input payloads (normal, malicious, edge cases)redirectPagevalues (local paths, external URLs, malicious payloads){"message": {"__proto__": {"polluted": true}}})Review Mongoose 6.12.3 vs 8.x trade-off - I chose 6.12.3 to avoid breaking changes with callback-based code throughout the application. Verify this trade-off is acceptable for your security requirements. Mongoose 8.x would require refactoring all database operations to use promises/async-await.
Verify allowlisted fields don't break legitimate use cases - The
save_account_detailsfunction now only accepts 5 fields:email,firstname,lastname,country,phone. Confirm no other fields should be accepted. Also verify the 1000-char length limit is reasonable.Recommended Test Plan
npm start{"layout": "../../malicious"}→ should be ignoredredirectPage=/admin→ should redirect to /adminredirectPage=https://evil.com→ should redirect to /admin (not external)Notes
Link to Devin run: https://app.devin.ai/sessions/5e811e3857f641d39e6cb78961f1eb7f
Requested by: @bnob-ship-it