Skip to content

Fix: Rate limiting & sensitive data exposure issues#5

Open
tinykav wants to merge 24 commits into
mainfrom
tiny
Open

Fix: Rate limiting & sensitive data exposure issues#5
tinykav wants to merge 24 commits into
mainfrom
tiny

Conversation

@tinykav

@tinykav tinykav commented Sep 22, 2025

Copy link
Copy Markdown
Contributor

Changes

  • Added express-rate-limit to all critical routes (/user, /tour, /booking, /review).
  • Configured stricter limiters for write-heavy routes (POST, PUT, DELETE).
  • Removed hardcoded MongoDB credentials.
  • Updated environment variables (.env) for DB connection strings and secrets.

Comment thread mainapp/backend/routes/booking.js Fixed
Comment thread mainapp/backend/routes/booking.js Fixed
Comment thread mainapp/backend/routes/booking.js Fixed
Comment thread mainapp/backend/routes/review.js Fixed
Comment thread mainapp/backend/routes/tour.js Fixed
Comment thread mainapp/backend/routes/user.js Fixed
Comment thread mainapp/backend/routes/user.js Fixed
const updateDoc = { $set: { ...updatePackageData } };
const result = await Packagecollection.updateOne(
filter,
updateDoc,

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query object depends on a
user-provided value
.

Copilot Autofix

AI 10 months ago

To fix this vulnerability, sanitize the user-provided data before including it in any database update operation. Specifically, ensure that no property keys in updatePackageData start with $ (to prevent operator injection), and ideally, allow updating only specific, whitelisted fields.
Here's what should be changed:

  • Before building updateDoc, filter updatePackageData so it contains only allowed keys (e.g., a whitelist of fields that are actually updatable).
  • Alternatively, at the very least, remove any keys that start with $ from updatePackageData (to prevent operator injection).
  • Apply this change in the PATCH /Package/:id route, before constructing updateDoc.

No new imports are strictly needed for the sanitization. The code can use a local helper function within the same file for filtering fields.


Suggested changeset 1
packageapp/backend/index.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packageapp/backend/index.js b/packageapp/backend/index.js
--- a/packageapp/backend/index.js
+++ b/packageapp/backend/index.js
@@ -63,7 +63,24 @@
     // Update a package
     app.patch("/Package/:id", writeLimiter, async (req, res) => {
       const id = req.params.id;
-      const updatePackageData = req.body;
+      const rawUpdatePackageData = req.body;
+
+      // Whitelist allowed fields to update; adjust as appropriate!
+      const allowedFields = ["name", "description", "price", "status"]; // <-- adapt to your schema
+      const updatePackageData = {};
+      for (const key of allowedFields) {
+        if (
+          Object.prototype.hasOwnProperty.call(rawUpdatePackageData, key) &&
+          typeof key === "string" &&
+          !key.startsWith("$")
+        ) {
+          updatePackageData[key] = rawUpdatePackageData[key];
+        }
+      }
+      // If nothing remains to update, reject
+      if (Object.keys(updatePackageData).length === 0) {
+        return res.status(400).send({ error: "No valid fields to update." });
+      }
       const filter = { _id: new ObjectId(id) };
       const options = { upsert: true };
       const updateDoc = { $set: { ...updatePackageData } };
EOF
@@ -63,7 +63,24 @@
// Update a package
app.patch("/Package/:id", writeLimiter, async (req, res) => {
const id = req.params.id;
const updatePackageData = req.body;
const rawUpdatePackageData = req.body;

// Whitelist allowed fields to update; adjust as appropriate!
const allowedFields = ["name", "description", "price", "status"]; // <-- adapt to your schema
const updatePackageData = {};
for (const key of allowedFields) {
if (
Object.prototype.hasOwnProperty.call(rawUpdatePackageData, key) &&
typeof key === "string" &&
!key.startsWith("$")
) {
updatePackageData[key] = rawUpdatePackageData[key];
}
}
// If nothing remains to update, reject
if (Object.keys(updatePackageData).length === 0) {
return res.status(400).send({ error: "No valid fields to update." });
}
const filter = { _id: new ObjectId(id) };
const options = { upsert: true };
const updateDoc = { $set: { ...updatePackageData } };
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread taskapp/backend/index.js
try {
const user = await authModel.findOne({ email: email });
if (user) res.json("Already Registerd");
const user = await authModel.findOne({ email });

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query object depends on a
user-provided value
.

Copilot Autofix

AI 10 months ago

To best fix this issue, we should ensure that the user input for email is strictly a string and does not allow for query objects or other types that could be interpreted by MongoDB as operators. There are two recommended ways:

  1. Input validation: Check that email is a string, and reject the request if it is not.
  2. MongoDB $eq operator: Use { email: { $eq: email } } to enforce that email is interpreted as a literal value.

The best fix is input validation, which gives immediate feedback to the client if the type is incorrect, but using the $eq operator provides a robust fallback that makes the query safe regardless. Implementing both is even better, but per instructions, we should minimize changes and maintain existing functionality.

Specific file/region to change:

  • In taskapp/backend/index.js, within the /register route (lines 72–88).

Required additions:

  • Before executing the query, check that email is a string.
  • If not, return a 400 response.

Alternatively, change the query to use $eq to ensure the value is strictly matched, but input validation provides a clearer error message to the user.


Suggested changeset 1
taskapp/backend/index.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/taskapp/backend/index.js b/taskapp/backend/index.js
--- a/taskapp/backend/index.js
+++ b/taskapp/backend/index.js
@@ -71,6 +71,9 @@
 // Register
 app.post("/register", authLimiter, async (req, res) => {
   const { userName, email, password } = req.body;
+  if (typeof email !== "string") {
+    return res.status(400).json({ error: "Invalid email type" });
+  }
   const salt = await bcrypt.genSalt(10);
   const hashedPassword = await bcrypt.hash(password, salt);
   const newAuth = new authModel({ userName, email, password: hashedPassword });
EOF
@@ -71,6 +71,9 @@
// Register
app.post("/register", authLimiter, async (req, res) => {
const { userName, email, password } = req.body;
if (typeof email !== "string") {
return res.status(400).json({ error: "Invalid email type" });
}
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const newAuth = new authModel({ userName, email, password: hashedPassword });
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread taskapp/backend/index.js
app.post("/forgotpass", authLimiter, async (req, res) => {
const { email } = req.body;
await authModel.findOne({ email: email }).then((user) => {
await authModel.findOne({ email }).then((user) => {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query object depends on a
user-provided value
.

Copilot Autofix

AI 10 months ago

To fix this vulnerability, we need to ensure that the user-supplied email value used in the MongoDB query is guaranteed to be a string literal, so that MongoDB interprets the query as a safe equality comparison and not as a potentially malicious query object. This can be accomplished by checking the type of email before running the query. If email is not a string, the handler should reject the request with a 400 Bad Request error and return early. This change should be implemented inside the /forgotpass handler before line 157. No additional methods or imports are needed, as basic JavaScript type checking (typeof) suffices.

Suggested changeset 1
taskapp/backend/index.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/taskapp/backend/index.js b/taskapp/backend/index.js
--- a/taskapp/backend/index.js
+++ b/taskapp/backend/index.js
@@ -154,6 +154,9 @@
 // Forgot Password
 app.post("/forgotpass", authLimiter, async (req, res) => {
   const { email } = req.body;
+  if (typeof email !== "string") {
+    return res.status(400).send({ Status: "Invalid email format" });
+  }
   await authModel.findOne({ email }).then((user) => {
     if (!user) return res.send({ Status: "Enter a valid email" });
 
EOF
@@ -154,6 +154,9 @@
// Forgot Password
app.post("/forgotpass", authLimiter, async (req, res) => {
const { email } = req.body;
if (typeof email !== "string") {
return res.status(400).send({ Status: "Invalid email format" });
}
await authModel.findOne({ email }).then((user) => {
if (!user) return res.send({ Status: "Enter a valid email" });

Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread mainapp/backend/routes/tour.js Fixed
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

2 participants