-
Notifications
You must be signed in to change notification settings - Fork 1
Enhance security and input validation across the application #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5308926
88e2fa5
50ece28
8b2172c
83e9391
8f626e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| # Environment Configuration Setup | ||
|
|
||
| ## Required .env Files | ||
|
|
||
| Create `.env` file in **each backend directory** with these variables: | ||
|
|
||
| ### 1. budgetapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=7000 | ||
| MONGODB_URL=mongodb://localhost:27017/wedding_budget | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-budget | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-budget | ||
| ``` | ||
|
|
||
| ### 2. eventapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=5003 | ||
| MONGO_CONNECTION_STRING=mongodb://localhost:27017/wedding_events | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-events | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-events | ||
| GOOGLE_CLIENT_ID=your-google-oauth-client-id | ||
| GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret | ||
| GOOGLE_CALLBACK_URL=http://localhost:5003/auth/google/callback | ||
| FRONTEND_URL=http://localhost:3003 | ||
| ``` | ||
|
|
||
| ### 3. guestapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=5002 | ||
| MONGO_URL=mongodb://localhost:27017/wedding_guests | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-guests | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-guests | ||
| ``` | ||
|
|
||
| ### 4. mainapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=8000 | ||
| MONGO_URI=mongodb://localhost:27017/wedding_main | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-main | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-main | ||
| ``` | ||
|
|
||
| ### 5. packageapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=5000 | ||
| MONGO_URI=mongodb://localhost:27017/wedding_packages | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-packages | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-packages | ||
| ``` | ||
|
|
||
| ### 6. vendorapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=5001 | ||
| MONGO_URL=mongodb://localhost:27017/wedding_vendors | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-vendors | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-vendors | ||
| SECRET_KEY=your-vendor-specific-secret-key-minimum-32-characters | ||
| ``` | ||
|
|
||
| ### 7. feedbackapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=3001 | ||
| MONGO_URI=mongodb://localhost:27017/wedding_feedback | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-feedback | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-feedback | ||
| ADMIN_PASSWORD=your-admin-password-for-basic-auth | ||
| ``` | ||
|
|
||
| ### 8. taskapp/backend/.env | ||
|
|
||
| ```bash | ||
| NODE_ENV=development | ||
| PORT=8080 | ||
| MONGO_URL=mongodb://localhost:27017/wedding_tasks | ||
| JWT_SECRET_KEY=your-super-secret-jwt-key-minimum-32-characters-tasks | ||
| SESSION_SECRET=your-super-secret-session-key-minimum-32-characters-tasks | ||
| FRONTEND_DOMAIN=http://localhost:3000 | ||
| GOOGLE_CLIENT_ID=your-google-oauth-client-id | ||
| GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret | ||
| FACEBOOK_CLIENT_ID=your-facebook-oauth-client-id | ||
| FACEBOOK_CLIENT_SECRET=your-facebook-oauth-client-secret | ||
| ``` | ||
|
|
||
| ## Security Requirements | ||
|
|
||
| ### Secret Key Generation | ||
|
|
||
| Use this command to generate secure keys: | ||
|
|
||
| ```bash | ||
| node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" | ||
| ``` | ||
|
|
||
| ### Database Setup | ||
|
|
||
| 1. Install MongoDB locally or use MongoDB Atlas | ||
| 2. Create separate databases for each service | ||
| 3. Ensure MongoDB authentication is enabled in production | ||
|
|
||
| ### OAuth Setup | ||
|
|
||
| 1. Create Google OAuth application at: https://console.cloud.google.com/ | ||
| 2. Create Facebook OAuth application at: https://developers.facebook.com/ | ||
| 3. Set appropriate callback URLs | ||
|
|
||
| ## Installation Script | ||
|
|
||
| Create this script to set up all environments: | ||
|
|
||
| ```bash | ||
| #!/bin/bash | ||
| # setup-env.sh | ||
|
|
||
| # Generate a secure key | ||
| generate_key() { | ||
| node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" | ||
| } | ||
|
|
||
| # Create .env files for each backend | ||
| backends=("budgetapp" "eventapp" "guestapp" "mainapp" "packageapp" "vendorapp" "feedbackapp" "taskapp") | ||
|
|
||
| for backend in "${backends[@]}"; do | ||
| if [ -d "${backend}/backend" ]; then | ||
| echo "Setting up ${backend}/backend/.env" | ||
| # Copy template and replace placeholders | ||
| # (Implementation depends on your setup) | ||
| fi | ||
| done | ||
|
|
||
| echo "Environment setup complete!" | ||
| echo "Remember to:" | ||
| echo "1. Update all placeholder values with actual secrets" | ||
| echo "2. Set up OAuth applications" | ||
| echo "3. Configure MongoDB connection strings" | ||
| echo "4. Never commit .env files to version control" | ||
| ``` | ||
|
|
||
| ## Verification | ||
|
|
||
| Test your setup: | ||
|
|
||
| ```bash | ||
| # Check each backend can start | ||
| cd budgetapp/backend && npm start | ||
| cd eventapp/backend && npm start | ||
| # ... etc for each backend | ||
| ``` | ||
|
|
||
| **IMPORTANT**: Never commit `.env` files to version control! |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,10 +1,21 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const express = require('express'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const express = require("express"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const router = express.Router(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const controller = require('../controllers/feedbackController'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const controller = require("../controllers/feedbackController"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { basicAuth, requireAdmin } = require("../../../middleware/basicAuth.js"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.get('/feedbacks',controller.getFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post('/createfeedback',controller.addFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post('/updatefeedback',controller.updateFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post('/deletefeedback',controller.deleteFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.get("/feedbacks", controller.getFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post("/createfeedback", basicAuth, controller.addFeedback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/updatefeedback", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| basicAuth, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requireAdmin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| controller.updateFeedback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / CodeQL Missing rate limiting High
This route handler performs
a database access Error loading related location Loading
Copilot AutofixAI 10 months ago To fix this problem, we should apply a rate-limiting middleware to the database-modifying routes:
This involves (1) adding the required import, (2) instantiating a rate limiter, and (3) editing the route definitions to use the rate limiter.
Suggested changeset
2
feedbackapp/backend/routes/feedbackRouter.js
feedbackapp/backend/package.json
Outside changed files
This fix introduces these dependencies
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.post( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/deletefeedback", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| basicAuth, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requireAdmin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| controller.deleteFeedback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / CodeQL Missing rate limiting High
This route handler performs
a database access Error loading related location Loading
Copilot AutofixAI 10 months ago To fix the issue, add rate limiting middleware to the Specifically:
Suggested changeset
2
feedbackapp/backend/routes/feedbackRouter.js
feedbackapp/backend/package.json
Outside changed files
This fix introduces these dependencies
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| module.exports = router; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| module.exports = router; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,44 @@ | ||
| const express = require('express'); | ||
| const express = require("express"); | ||
| const app = express(); | ||
| const cors = require('cors'); | ||
| const dotenv = require('dotenv'); | ||
| const cors = require("cors"); | ||
| const dotenv = require("dotenv"); | ||
| dotenv.config(); | ||
|
|
||
| const port = 3001; | ||
| const host = 'localhost'; | ||
| const mongoose = require('mongoose'); | ||
| const router = require('./routes/feedbackRouter'); | ||
| const host = "localhost"; | ||
| const mongoose = require("mongoose"); | ||
| const router = require("./routes/feedbackRouter"); | ||
|
|
||
| app.use(cors()); //cors origin unblocking(cross origine resoures sharing) | ||
| app.use( | ||
| cors({ | ||
| origin: [ | ||
| "http://localhost:3000", | ||
| "http://localhost:3001", | ||
| "http://localhost:3004", | ||
| ], | ||
| credentials: true, | ||
| methods: ["GET", "POST", "PUT", "DELETE", "PATCH"], | ||
| allowedHeaders: ["Content-Type", "Authorization"], | ||
| }) | ||
| ); //cors origin blocking for security | ||
| app.use(express.json()); | ||
|
|
||
| // Use environment variable for MongoDB URI | ||
| const uri = process.env.MONGO_URI; | ||
| const connect = async () => { | ||
| try { | ||
| await mongoose.connect(uri); | ||
| console.log('connected to mongoDB'); | ||
| } catch (error) { | ||
| console.log('mongoDB error: ',error); | ||
| } | ||
| try { | ||
| await mongoose.connect(uri); | ||
| console.log("connected to mongoDB"); | ||
| } catch (error) { | ||
| console.log("mongoDB error: ", error); | ||
| } | ||
| }; | ||
|
|
||
| connect(); | ||
|
|
||
| //call back function | ||
| const server = app.listen(port,host, () => { | ||
| console.log(`Node server is listing to ${server.address().port}`) | ||
| const server = app.listen(port, host, () => { | ||
| console.log(`Node server is listing to ${server.address().port}`); | ||
| }); | ||
|
|
||
| app.use('/api',router); | ||
| app.use("/api", router); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| // Basic authentication middleware for applications without full user management | ||
| const basicAuth = (req, res, next) => { | ||
| const authHeader = req.headers.authorization; | ||
|
|
||
| if (!authHeader || !authHeader.startsWith("Basic ")) { | ||
| return res.status(401).json({ | ||
| error: "Authentication required", | ||
| code: "NO_AUTH", | ||
| }); | ||
| } | ||
|
|
||
| try { | ||
| const base64Credentials = authHeader.substring(6); | ||
| const credentials = Buffer.from(base64Credentials, "base64").toString( | ||
| "ascii" | ||
| ); | ||
| const [username, password] = credentials.split(":"); | ||
|
|
||
| // Simple admin check (in production, use proper user management) | ||
| if (username === "admin" && password === process.env.ADMIN_PASSWORD) { | ||
| req.user = { role: "admin", username: "admin" }; | ||
| next(); | ||
| } else { | ||
| return res.status(401).json({ | ||
| error: "Invalid credentials", | ||
| code: "INVALID_CREDENTIALS", | ||
| }); | ||
| } | ||
| } catch (error) { | ||
| return res.status(401).json({ | ||
| error: "Invalid authorization header", | ||
| code: "INVALID_AUTH_HEADER", | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| // Role-based authorization | ||
| const requireAdmin = (req, res, next) => { | ||
| if (!req.user || req.user.role !== "admin") { | ||
| return res.status(403).json({ | ||
| error: "Admin access required", | ||
| code: "ADMIN_REQUIRED", | ||
| }); | ||
| } | ||
| next(); | ||
| }; | ||
|
|
||
| module.exports = { | ||
| basicAuth, | ||
| requireAdmin, | ||
| }; |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Copilot Autofix
AI 10 months ago
To fix the missing rate limiting on the
/feedbacksroute, add a rate-limiting middleware before thecontroller.getFeedbackhandler on this route. The best practice is to use a well-known rate-limiting package,express-rate-limit, which is easy to use and effective. Add the import forexpress-rate-limit, define a limiter with a reasonable limit (e.g., 100 requests per 15 minutes), and insert the limiter as middleware to the/feedbacksroute. Restrict changes strictly to the code you've been shown: only edit feedbackapp/backend/routes/feedbackRouter.js and add minimal required code in visible regions.