Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
446 changes: 446 additions & 0 deletions direct-nosql-injection-test.js

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion guestapp/backend/controllers/admin-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,18 @@ const adminLogIn = async (req, res) => {

const getAdminDetail = async (req, res) => {
try {
let admin = await Admin.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid admin ID format",
code: "INVALID_OBJECT_ID",
});
}

let admin = await Admin.findById(id);
if (admin) {
admin.password = undefined;
res.send(admin);
Expand Down
35 changes: 30 additions & 5 deletions guestapp/backend/controllers/guest_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,18 @@ const getGuests = async (req, res) => {

const getGuestDetail = async (req, res) => {
try {
// Validate ObjectId to prevent NoSQL injection
if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Comprehensive ObjectId validation to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid guest ID format",
code: "INVALID_OBJECT_ID",
});
}

let guest = await Guest.findById(req.params.id)
let guest = await Guest.findById(id)
.populate("event", "eventName")
.populate("stableName", "stableName")
.populate("examResult.subName", "subName")
Expand Down Expand Up @@ -182,7 +185,18 @@ const updateExamResult = async (req, res) => {
const { subName, obligesObtained } = req.body;

try {
const guest = await Guest.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid guest ID format",
code: "INVALID_OBJECT_ID",
});
}

const guest = await Guest.findById(id);

if (!guest) {
return res.send({ message: "Guest not found" });
Expand All @@ -209,7 +223,18 @@ const guestAttendance = async (req, res) => {
const { subName, status, date } = req.body;

try {
const guest = await Guest.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid guest ID format",
code: "INVALID_OBJECT_ID",
});
}

const guest = await Guest.findById(id);

if (!guest) {
return res.send({ message: "Guest not found" });
Expand Down
13 changes: 12 additions & 1 deletion guestapp/backend/controllers/preference-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,18 @@ const freePreferenceList = async (req, res) => {

const getPreferenceDetail = async (req, res) => {
try {
let preference = await Preference.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid preference ID format",
code: "INVALID_OBJECT_ID",
});
}

let preference = await Preference.findById(id);
if (preference) {
preference = await preference.populate("stableName", "stableName");
preference = await preference.populate("vendor", "name");
Expand Down
39 changes: 36 additions & 3 deletions guestapp/backend/controllers/table-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,18 @@ const stableCreate = async (req, res) => {

const stableList = async (req, res) => {
try {
let stablees = await Stable.find({ event: req.params.id });
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid event ID format",
code: "INVALID_OBJECT_ID",
});
}

let stablees = await Stable.find({ event: id });
if (stablees.length > 0) {
res.send(stablees);
} else {
Expand All @@ -41,7 +52,18 @@ const stableList = async (req, res) => {

const getStableDetail = async (req, res) => {
try {
let stable = await Stable.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid stable ID format",
code: "INVALID_OBJECT_ID",
});
}

let stable = await Stable.findById(id);
if (stable) {
stable = await stable.populate("event", "eventName");
res.send(stable);
Expand All @@ -55,7 +77,18 @@ const getStableDetail = async (req, res) => {

const getStableGuests = async (req, res) => {
try {
let guests = await Guest.find({ stableName: req.params.id });
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid stable ID format",
code: "INVALID_OBJECT_ID",
});
}

let guests = await Guest.find({ stableName: id });
if (guests.length > 0) {
let modifiedGuests = guests.map((guest) => {
return { ...guest._doc, password: undefined };
Expand Down
58 changes: 36 additions & 22 deletions guestapp/backend/controllers/vendor-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const vendorRegister = async (req, res) => {
role,
event,
teachPreference,
teachStable
teachStable,
});

const existingVendorByEmail = await Vendor.findOne({ email });
Expand All @@ -27,7 +27,7 @@ const vendorRegister = async (req, res) => {
} else {
let result = await vendor.save();
await Preference.findByIdAndUpdate(teachPreference, {
vendor: vendor._id
vendor: vendor._id,
});
result.password = undefined;
res.send(result);
Expand Down Expand Up @@ -65,18 +65,18 @@ const vendorLogIn = async (req, res) => {

const getVendors = async (req, res) => {
try {
// Validate ObjectId to prevent NoSQL injection
if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Comprehensive ObjectId validation to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid event ID format",
code: "INVALID_OBJECT_ID"
code: "INVALID_OBJECT_ID",
});
}

// Convert to ObjectId for type safety
const eventId = mongoose.Types.ObjectId(req.params.id);

let vendors = await Vendor.find({ event: eventId })
let vendors = await Vendor.find({ event: id })
.populate("teachPreference", "subName")
.populate("teachStable", "stableName");

Expand All @@ -92,22 +92,25 @@ const getVendors = async (req, res) => {
console.error("Vendors retrieval error:", err.message);
res.status(500).json({
error: "Failed to retrieve vendors",
code: "VENDORS_RETRIEVAL_ERROR"
code: "VENDORS_RETRIEVAL_ERROR",
});
}
};

const getVendorDetail = async (req, res) => {
try {
// Validate ObjectId to prevent NoSQL injection
if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Comprehensive ObjectId validation to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid vendor ID format",
code: "INVALID_OBJECT_ID"
code: "INVALID_OBJECT_ID",
});
}

let vendor = await Vendor.findById(req.params.id)
let vendor = await Vendor.findById(id)
.populate("teachPreference", "subName sessions")
.populate("event", "eventName")
.populate("teachStable", "stableName");
Expand All @@ -118,14 +121,14 @@ const getVendorDetail = async (req, res) => {
} else {
res.status(404).json({
error: "Vendor not found",
code: "VENDOR_NOT_FOUND"
code: "VENDOR_NOT_FOUND",
});
}
} catch (err) {
console.error("Vendor detail error:", err.message);
res.status(500).json({
error: "Failed to retrieve vendor details",
code: "VENDOR_DETAIL_ERROR"
code: "VENDOR_DETAIL_ERROR",
});
}
};
Expand All @@ -140,7 +143,7 @@ const updateVendorPreference = async (req, res) => {
);

await Preference.findByIdAndUpdate(teachPreference, {
vendor: updatedVendor._id
vendor: updatedVendor._id,
});

res.send(updatedVendor);
Expand Down Expand Up @@ -180,7 +183,7 @@ const deleteVendors = async (req, res) => {
await Preference.updateMany(
{
vendor: { $in: deletedVendors.map((vendor) => vendor._id) },
vendor: { $exists: true }
vendor: { $exists: true },
},
{ $unset: { vendor: "" }, $unset: { vendor: null } }
);
Expand All @@ -194,7 +197,7 @@ const deleteVendors = async (req, res) => {
const deleteVendorsByTable = async (req, res) => {
try {
const deletionResult = await Vendor.deleteMany({
stableName: req.params.id
stableName: req.params.id,
});

const deletedCount = deletionResult.deletedCount || 0;
Expand All @@ -209,7 +212,7 @@ const deleteVendorsByTable = async (req, res) => {
await Preference.updateMany(
{
vendor: { $in: deletedVendors.map((vendor) => vendor._id) },
vendor: { $exists: true }
vendor: { $exists: true },
},
{ $unset: { vendor: "" }, $unset: { vendor: null } }
);
Expand All @@ -224,7 +227,18 @@ const vendorAttendance = async (req, res) => {
const { status, date } = req.body;

try {
const vendor = await Vendor.findById(req.params.id);
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid vendor ID format",
code: "INVALID_OBJECT_ID",
});
}

const vendor = await Vendor.findById(id);

if (!vendor) {
return res.send({ message: "Vendor not found" });
Expand Down Expand Up @@ -256,5 +270,5 @@ module.exports = {
deleteVendor,
deleteVendors,
deleteVendorsByTable,
vendorAttendance
vendorAttendance,
};
31 changes: 28 additions & 3 deletions packageapp/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@
"/Package/:id",
authenticateUser,
requireRole(["admin"]),
validateObjectId,
validateInput(schemas.package),
async (req, res) => {
try {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid package ID format",
code: "INVALID_OBJECT_ID",
});
}
const updatePackageData = req.body;
const filter = { _id: new ObjectId(id) };
const options = { upsert: false }; // Don't create if not exists
Expand Down Expand Up @@ -148,10 +156,18 @@
"/Package/:id",
authenticateUser,
requireRole(["admin"]),
validateObjectId,
async (req, res) => {
try {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid package ID format",
code: "INVALID_OBJECT_ID",
});
}
const filter = { _id: new ObjectId(id) };

// Check if package exists
Expand Down Expand Up @@ -181,31 +197,40 @@

//To get single package data

app.get("/package/:id", validateObjectId, async (req, res) => {
app.get("/package/:id", async (req, res) => {
try {
// ✅ DIRECT NoSQL INJECTION PROTECTION
const id = req.params.id;

// Validate ObjectId format to prevent NoSQL injection
if (!id || typeof id !== "string" || !/^[0-9a-fA-F]{24}$/.test(id)) {
return res.status(400).json({
error: "Invalid package ID format",
code: "INVALID_OBJECT_ID",
});
}
const filter = { _id: new ObjectId(id) };
const result = await Packagecollection.findOne(filter);

if (result) {
res.json({
success: true,
data: result,
});
} else {
res.status(404).json({
error: "Package not found",
code: "PACKAGE_NOT_FOUND",
});
}
} catch (error) {
console.error("Package retrieval error:", error);
res.status(500).json({
error: "Failed to retrieve package",
code: "RETRIEVAL_FAILED",
});
}
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

// Send a ping to confirm a successful connection

Expand Down
Loading