Skip to content

Validation: Username and email lack input sanitization, vulnerable to injection and script attacks if stored in database #700

@anshul23102

Description

@anshul23102

Problem

Username and email are not sanitized before storage (backend/routes/auth.js line 21). Malicious input could be stored and later executed.


Technical Details

File: backend/routes/auth.js
Line: 21

const newUser = new User({ username, email, password });

While Zod validates format, it doesn't sanitize special characters or scripts.

Attack Scenarios

Stored XSS via Username:

  • Username: <img src=x onerror="alert('xss')">
  • Stored in database as-is
  • When displayed in UI: JavaScript executes

MongoDB Injection:

  • Email: {\"\\$ne\": null}
  • If used in query without proper parameterization: User.findOne({email: email})
  • Could bypass authentication

Recommended Solution

Sanitize and validate inputs:

const sanitizeHtml = require('sanitize-html');
const mongoSanitize = require('express-mongo-sanitize');

// In app setup:
app.use(mongoSanitize());  // Prevents MongoDB injection

// In auth route:
router.post("/signup", validateRequest(signupSchema), async (req, res) => {
  const { username, email, password } = req.body;
  
  try {
    // Sanitize inputs
    const cleanUsername = sanitizeHtml(username.trim(), {
      allowedTags: [],
      allowedAttributes: {}
    });
    
    const cleanEmail = email.toLowerCase().trim();
    
    // Validate cleaned inputs
    if (cleanUsername !== username) {
      return res.status(400).json({
        message: 'Username contains invalid characters'
      });
    }
    
    const existingUser = await User.findOne({
      $or: [{ email: cleanEmail }, { username: cleanUsername }]
    });
    
    if (existingUser) {
      return res.status(400).json({
        message: 'Signup failed. Please try again.'
      });
    }
    
    // Store sanitized values
    const newUser = new User({
      username: cleanUsername,
      email: cleanEmail,
      password
    });
    
    await newUser.save();
    
    res.status(201).json({
      message: 'Account created successfully'
    });
  } catch (err) {
    res.status(400).json({
      message: 'Signup failed. Please try again.'
    });
  }
});

Testing Strategy

  • Test: HTML/script injection rejected
  • Test: MongoDB operators filtered
  • Test: Valid usernames accepted
  • XSS test: No JavaScript execution in username display
  • Injection test: Payloads neutralized

Program Template

  • GSSoC '26

Suggested Labels

security, input-sanitization, xss, mongodb-injection, gssoc-eligible

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions