Enforce email uniqueness during registration process
import express from 'express';
const app = express();
app.use(express.json());
interface User {
id: number;
email: string;
}
const users: User[] = [];
app.post('/register', (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: 'Email is required' });
}
const userExists = users.some((user) => user.email === email);
if (userExists) {
return res.status(400).json({ error: 'Email already exists' });
}
users.push({ id: users.length + 1, email });
return res.status(200).json({ message: 'User registered successfully' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The vulnerability in this code lies in the email uniqueness check during the registration process. The code allows the plus character (+) in the email, which can be abused by an attacker to create multiple accounts pointing to the same email.
In the code, when a user tries to register, the email is extracted from the request body. If the email is not provided, a 400 Bad Request response is returned, indicating that the email is required.
Next, the code checks if the email already exists in the
users
array by using the
some
method. If a user with the same email already exists, a 400 Bad Request response is returned, indicating that the email already exists.
However, the code does not properly validate the uniqueness of the email. It only checks if there is any user with the exact same email in the
users
array. This means that an attacker can abuse the plus character in the email to create multiple accounts with different email variations, but all pointing to the same email inbox.
For example, if the email "example@gmail.com" is already registered, an attacker can register with "example+1@gmail.com", "example+2@gmail.com", and so on, creating multiple accounts that all point to the same email inbox.
This vulnerability allows an attacker to bypass the email uniqueness check and create multiple accounts with the same email, which can lead to abuse of the system or potential security issues.
import express from 'express';
const app = express();
app.use(express.json());
interface User {
id: number;
email: string;
}
const users: User[] = [];
const uniqueEmails = new Set();
app.post('/register', (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: 'Email is required' });
}
if (uniqueEmails.has(email)) {
return res.status(400).json({ error: 'Email already exists' });
}
uniqueEmails.add(email);
const newUser: User = {
id: users.length + 1,
email,
};
users.push(newUser);
return res.status(200).json({ message: 'User registered successfully' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The fixed code addresses the vulnerability by properly verifying the uniqueness of email addresses during the registration process.
First, the code imports the necessary dependencies, including the Express framework.
The code defines an interface called
User
which represents the structure of a user object. It has two properties:
id
of type number and
email
of type string.
Next, the code initializes an empty array called
users
to store registered users and a new Set called
uniqueEmails
to keep track of unique email addresses.
The code sets up an Express application and configures it to parse JSON data.
The code defines a POST route handler for the '/register' endpoint. Inside the handler, it extracts the
email
property from the request body.
The code then checks if the
email
is empty. If it is, it returns a 400 status code with an error message indicating that the email is required.
Next, the code checks if the
uniqueEmails
Set already contains the provided email. If it does, it returns a 400 status code with an error message indicating that the email already exists.
If the email is unique, the code adds it to the
uniqueEmails
Set to ensure uniqueness.
The code then creates a new
User
object with an
id
value based on the length of the
users
array plus one, and assigns the provided email to the
email
property.
The new user object is pushed to the
users
array.
Finally, the code returns a 200 status code with a success message indicating that the user has been registered successfully.
The code also starts the Express server and listens on port 3000.
By using a Set to keep track of unique email addresses and checking for duplicates before registering a new user, the code ensures that each email can only be associated with one user account, effectively addressing the vulnerability.