-
Notifications
You must be signed in to change notification settings - Fork 0
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
Implement a command bridge between servers and the API #106
base: master
Are you sure you want to change the base?
Conversation
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99) * Delete message after filtering prohibited content. * Fix spacing in network log messages. * Make usernames more presentable in logs. * Remove deleted channel field from being mentioned twice. * Fixed issue where filter errors after response is sent. * Changed from HEX to Colour * Add /poll command. * Add page descriptions to headers. * Added keywords and SEO option to configuration. * Add documentation badges for list and editors. * Push mobile view changes for session views. * Resolved mobile styling issues with dashboard views. * Added a staffChannel config option and a /staffhelp command * Resolve issues with cookie banner not showing on /register * Made urgent change to hasPermission, allowing non-logged in users to view admin panel. * Reformat all project files using Prettier. (#90) * Commit not found. * Prettify all JS and JSON files. * Resolve issue with logout crashing. * Separate redirect route into own file, add config option for kb and added issue tracker route. * Change node engine to support node 18. (#92) * Implementation of a Ranks/donation page. (#91) * Commence work on /ranks page and Tebex integration. * Transitioning back to JSON file, using catagory and packages * Finish rank page implementation. * Update perks. * Implement a call to action button style instead and make mobile friendly. * Made the server name look to site config for /ranks * Change rank page descriptor. * Commit start of rego process. * Add more routes * Implement 2fa interactive form element. * Install packages for email integration * Implement email template draft and smtp credentials. * Commence more work on controller and tests for emails. * Working on pathing. * Fix pathing on email template. * Add email header and footer and fix up routes. * Add a rough template draft of registration * Change registration gateway to discord, commence working on Minecraft link. * Add user verification via /verify * Remove all old rego code and mentions to passwords, remove email views and partials. * Add token code expiry and draft a expiry cron task. * Refactor getUser() into UserGetter * Push user verification service. * Commence drafting profiles and finalising login gateway * Add coming soon alerts on profile features. * Commit more profile work and db profile changes. * Applied permissions to profile. * Add example.env and config files. * Added Minecraft login and chat audits, also added website login. * Added discord voice and message audit events. * Filled in fields for audit to complete feature development. * Start work on profile editor. * Start implementing social connections into editor. * Finalise design for profile editor. * Implemented all of the base work for API routes and controllers. * Start on profile/display in editor and fix issue with Gravatar. * Finalise Social Connections in display and editor. * Fix permission node of everyone able to see dashboard, and open new tab for social connections. * Audit: If no data, then display no data instead of invalid date * Added profile stats for total logins and playtime. * Add latest session with online and offline indicators. * Add support for verification server in /server * Resolved issues with Server types displaying all instead of their type. * Create dbupgrade.sql Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql * Commence port to new schema. * Fix result type return in user api and added 17 global images. * Make unregistered failure link back to rego page. * Set audit to skip for discord voice and chat if discord is not linked. * Resolved issues with user api creation. * Resolve issues with messages attempting to send to channels. * Require the webhook package. * Rollback to d70b343 * Changes to user route and troubleshooting discord login. * Remove redirect returns. * Add troubleshooting to callback. * Push further troubleshooting. * Add troubleshooting to isRegistered * Add additional check and troubleshooting * Commit * Add a build command. * Fix Discord oAuth (#98) * Wrap in string for ID and secret. * Add logging to callback. * Add more logging. * Add more testing * got here marker. * move marker. * Move marker * update marker * marker 4, reveal session * Add permission data log * Fix issues with loading profile editor. * On profile updates, redirect to profile. * Add steam social and profanity filter to interests. * Add ability for linked accounts to not trigger linking codes. * Push profile command. * Add ranks api to fetch by rank and user. * Add debug for user permissions --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]> * Added rank permissions context into login sessions and clean up profile command. (#100) * Start rank perms scope on user implementation * Fix getUserPermissions to scope in rank permission nodes. * Remove the zanderdev prefix from permissions lookup. * Replace with amended getUserLastSession() to stop profiles from crashing. * Refactor to stop nulls from crashing the API * Removed all Craftatar discord side features due to traffic amplification attacks. * Add ` in profile title username to keep formatting. * Start work on report and locking behind login session. * Added report support via in-game and web. * Add discord /report command. * Add feature blocks to apply, ranks and report. Fix staffhelp command. * move reporting to true * Get a timeout on db and refactor to CraftHead. * Draft reports tab in profile. * Finish reporting badge. * Remove report log. * Add safe server to features on home. --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]>
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99) * Delete message after filtering prohibited content. * Fix spacing in network log messages. * Make usernames more presentable in logs. * Remove deleted channel field from being mentioned twice. * Fixed issue where filter errors after response is sent. * Changed from HEX to Colour * Add /poll command. * Add page descriptions to headers. * Added keywords and SEO option to configuration. * Add documentation badges for list and editors. * Push mobile view changes for session views. * Resolved mobile styling issues with dashboard views. * Added a staffChannel config option and a /staffhelp command * Resolve issues with cookie banner not showing on /register * Made urgent change to hasPermission, allowing non-logged in users to view admin panel. * Reformat all project files using Prettier. (#90) * Commit not found. * Prettify all JS and JSON files. * Resolve issue with logout crashing. * Separate redirect route into own file, add config option for kb and added issue tracker route. * Change node engine to support node 18. (#92) * Implementation of a Ranks/donation page. (#91) * Commence work on /ranks page and Tebex integration. * Transitioning back to JSON file, using catagory and packages * Finish rank page implementation. * Update perks. * Implement a call to action button style instead and make mobile friendly. * Made the server name look to site config for /ranks * Change rank page descriptor. * Commit start of rego process. * Add more routes * Implement 2fa interactive form element. * Install packages for email integration * Implement email template draft and smtp credentials. * Commence more work on controller and tests for emails. * Working on pathing. * Fix pathing on email template. * Add email header and footer and fix up routes. * Add a rough template draft of registration * Change registration gateway to discord, commence working on Minecraft link. * Add user verification via /verify * Remove all old rego code and mentions to passwords, remove email views and partials. * Add token code expiry and draft a expiry cron task. * Refactor getUser() into UserGetter * Push user verification service. * Commence drafting profiles and finalising login gateway * Add coming soon alerts on profile features. * Commit more profile work and db profile changes. * Applied permissions to profile. * Add example.env and config files. * Added Minecraft login and chat audits, also added website login. * Added discord voice and message audit events. * Filled in fields for audit to complete feature development. * Start work on profile editor. * Start implementing social connections into editor. * Finalise design for profile editor. * Implemented all of the base work for API routes and controllers. * Start on profile/display in editor and fix issue with Gravatar. * Finalise Social Connections in display and editor. * Fix permission node of everyone able to see dashboard, and open new tab for social connections. * Audit: If no data, then display no data instead of invalid date * Added profile stats for total logins and playtime. * Add latest session with online and offline indicators. * Add support for verification server in /server * Resolved issues with Server types displaying all instead of their type. * Create dbupgrade.sql Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql * Commence port to new schema. * Fix result type return in user api and added 17 global images. * Make unregistered failure link back to rego page. * Set audit to skip for discord voice and chat if discord is not linked. * Resolved issues with user api creation. * Resolve issues with messages attempting to send to channels. * Require the webhook package. * Rollback to d70b343 * Changes to user route and troubleshooting discord login. * Remove redirect returns. * Add troubleshooting to callback. * Push further troubleshooting. * Add troubleshooting to isRegistered * Add additional check and troubleshooting * Commit * Add a build command. * Fix Discord oAuth (#98) * Wrap in string for ID and secret. * Add logging to callback. * Add more logging. * Add more testing * got here marker. * move marker. * Move marker * update marker * marker 4, reveal session * Add permission data log * Fix issues with loading profile editor. * On profile updates, redirect to profile. * Add steam social and profanity filter to interests. * Add ability for linked accounts to not trigger linking codes. * Push profile command. * Add ranks api to fetch by rank and user. * Add debug for user permissions --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]> * Added rank permissions context into login sessions and clean up profile command. (#100) * Start rank perms scope on user implementation * Fix getUserPermissions to scope in rank permission nodes. * Remove the zanderdev prefix from permissions lookup. * Replace with amended getUserLastSession() to stop profiles from crashing. * Refactor to stop nulls from crashing the API * Removed all Craftatar discord side features due to traffic amplification attacks. * Add ` in profile title username to keep formatting. * Start work on report and locking behind login session. * Added report support via in-game and web. * Add discord /report command. * Add feature blocks to apply, ranks and report. Fix staffhelp command. * move reporting to true * Add vault get/add/update/delete * Add description and /vault command * Fix edit query on vault * Change from announcementSlug to announcementId * Commit Application api change --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]>
|
||
try { | ||
function getBridge(dbQuery) { | ||
db.query(dbQuery, function (error, results, fields) { |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources High
user-provided value
This query string depends on a
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we should use query parameters to safely embed user-provided data into the SQL query. This approach prevents SQL injection by ensuring that the user input is treated as a literal value rather than executable code.
- Modify the
getBridge
function to accept query parameters. - Update the SQL query strings to use placeholders for the parameters.
- Pass the user-provided data as parameters to the
db.query
function.
-
Copy modified lines R12-R13 -
Copy modified lines R37-R38 -
Copy modified lines R43-R44 -
Copy modified line R49
@@ -11,4 +11,4 @@ | ||
try { | ||
function getBridge(dbQuery) { | ||
db.query(dbQuery, function (error, results, fields) { | ||
function getBridge(dbQuery, queryParams) { | ||
db.query(dbQuery, queryParams, function (error, results, fields) { | ||
if (error) { | ||
@@ -36,4 +36,4 @@ | ||
if (bridgeId) { | ||
let dbQuery = `SELECT * FROM bridge WHERE bridgeId=${bridgeId};`; | ||
getBridge(dbQuery); | ||
let dbQuery = `SELECT * FROM bridge WHERE bridgeId=?;`; | ||
getBridge(dbQuery, [bridgeId]); | ||
} | ||
@@ -42,4 +42,4 @@ | ||
if (targetServer) { | ||
let dbQuery = `SELECT * FROM bridge WHERE targetServer='${targetServer}' AND processed=0;`; | ||
getBridge(dbQuery); | ||
let dbQuery = `SELECT * FROM bridge WHERE targetServer=? AND processed=0;`; | ||
getBridge(dbQuery, [targetServer]); | ||
} | ||
@@ -48,3 +48,3 @@ | ||
let dbQuery = `SELECT * FROM bridge;`; | ||
getBridge(dbQuery); | ||
getBridge(dbQuery, []); | ||
} catch (error) { |
app.post(baseEndpoint + "/command/add", async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
|
||
const command = required(req.body, "command", res); | ||
const targetServer = required(req.body, "targetServer", res); | ||
|
||
try { | ||
db.query( | ||
`INSERT INTO bridge (command, targetServer) VALUES (?, ?)`, | ||
[command, targetServer], | ||
function (error, results, fields) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
message: `New Bridge command added for ${targetServer}: ${command}`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the route handlers that perform database access. The best way to achieve this is by using the express-rate-limit
middleware. This middleware allows us to set a maximum number of requests a user can make within a specified time window. We will apply this middleware to the relevant routes to ensure they are protected against excessive requests.
We will:
- Install the
express-rate-limit
package. - Import the
express-rate-limit
package in the file. - Set up a rate limiter with appropriate configuration.
- Apply the rate limiter to the relevant routes.
-
Copy modified line R2 -
Copy modified lines R5-R8 -
Copy modified line R65 -
Copy modified line R99 -
Copy modified line R129
@@ -1,4 +1,9 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
export default function bridgeApiRoute(app, config, db, features, lang) { | ||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
const baseEndpoint = "/api/bridge"; | ||
@@ -59,3 +64,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/add", async function (req, res) { | ||
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -93,3 +98,3 @@ | ||
|
||
app.post(baseEndpoint + "/clear", async function (req, res) { | ||
app.post(baseEndpoint + "/clear", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -123,3 +128,3 @@ | ||
|
||
app.get(baseEndpoint + "/server/get", async function (req, res) { | ||
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
api/routes/bridge.js
Outdated
app.post(baseEndpoint + "/command/process", async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
|
||
const bridgeId = required(req.body, "bridgeId", res); | ||
|
||
try { | ||
const fetchURL = `${process.env.siteAddress}/api/bridge/get?id=${bridgeId}`; | ||
const response = await fetch(fetchURL, { | ||
headers: { "x-access-token": process.env.apiKey }, | ||
}); | ||
const bridgeApiData = await response.json(); | ||
|
||
db.query( | ||
`UPDATE bridge SET processed=? WHERE bridgeId=?;`, | ||
[1, bridgeId], | ||
function (error, results, fields) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Bridge ID ${bridgeId} has been executed.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the Express application. The best way to do this is by using the express-rate-limit
package, which allows us to easily set up and apply rate limiting to all routes or specific routes.
- Install the
express-rate-limit
package. - Import the
express-rate-limit
package in theapi/routes/bridge.js
file. - Set up a rate limiter with appropriate configuration (e.g., maximum number of requests per time window).
- Apply the rate limiter to the routes that perform database access operations.
-
Copy modified line R2 -
Copy modified lines R6-R9 -
Copy modified line R11 -
Copy modified line R65 -
Copy modified line R99 -
Copy modified line R129 -
Copy modified line R159 -
Copy modified line R193
@@ -1,2 +1,3 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
@@ -4,4 +5,8 @@ | ||
const baseEndpoint = "/api/bridge"; | ||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { | ||
app.get(baseEndpoint + "/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -59,3 +64,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/add", async function (req, res) { | ||
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -93,3 +98,3 @@ | ||
|
||
app.post(baseEndpoint + "/clear", async function (req, res) { | ||
app.post(baseEndpoint + "/clear", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -123,3 +128,3 @@ | ||
|
||
app.get(baseEndpoint + "/server/get", async function (req, res) { | ||
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -153,3 +158,3 @@ | ||
|
||
app.post(baseEndpoint + "/server/update", async function (req, res) { | ||
app.post(baseEndpoint + "/server/update", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -187,3 +192,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/process", async function (req, res) { | ||
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
app.post(baseEndpoint + "/create", async function (req, res) { | ||
isFeatureEnabled(features.report, res, lang); | ||
|
||
const reporterUser = required(req.body, "reporterUser", res); | ||
const reportedUser = required(req.body, "reportedUser", res); | ||
const reportReason = required(req.body, "reportReason", res); | ||
const reportReasonEvidence = optional( | ||
req.body, | ||
"reportReasonEvidence", | ||
res | ||
); | ||
const reportPlatform = required(req.body, "reportPlatform", res); | ||
|
||
try { | ||
db.query( | ||
` | ||
INSERT INTO | ||
reports | ||
( | ||
reporterId, | ||
reportedUser, | ||
reportReason, | ||
reportReasonEvidence, | ||
reportPlatform | ||
) VALUES ((SELECT userId FROM users WHERE username=?), ?, ?, ?, ?)`, | ||
[ | ||
reporterUser, | ||
reportedUser, | ||
reportReason, | ||
reportReasonEvidence, | ||
reportPlatform, | ||
], | ||
function (error, results, fields) { | ||
console.log(req.body); | ||
|
||
if (error) { | ||
console.log(error); | ||
console.log(results); | ||
|
||
return res.send({ | ||
success: false, | ||
message: `Report has failed, please try again later.`, | ||
}); | ||
} else { | ||
setBannerCookie("success", "Report has been sent.", res); | ||
|
||
try { | ||
const staffChannelHook = new Webhook( | ||
config.discord.webhooks.staffChannel | ||
); | ||
|
||
const embed = new MessageBuilder() | ||
.setTitle(`New Report: ${reportedUser}`) | ||
.addField("Report Platform", reportPlatform, true) | ||
.addField("Report By", reporterUser, true) | ||
.addField("Report Reason", reportReason) | ||
.setColor(Colors.Red) | ||
.setTimestamp(); | ||
|
||
if (reportReasonEvidence) { | ||
embed.addField("Report Evidence", reportReasonEvidence); | ||
} | ||
|
||
staffChannelHook.send(embed); | ||
} catch (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Thanks for your submission: ${reportedUser} for ${reportReason}.`, | ||
}); | ||
} | ||
} | ||
); | ||
} catch (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the route handlers that perform database access. The best way to achieve this is by using the express-rate-limit
package, which allows us to easily set up and apply rate limiting middleware to our Express routes.
- Install the
express-rate-limit
package. - Import the
express-rate-limit
package in the file. - Set up a rate limiter with appropriate configuration.
- Apply the rate limiter to the relevant routes.
-
Copy modified line R4 -
Copy modified lines R9-R14 -
Copy modified line R16 -
Copy modified line R62
@@ -3,2 +3,3 @@ | ||
import { Colors } from "discord.js"; | ||
import rateLimit from 'express-rate-limit'; | ||
|
||
@@ -7,4 +8,10 @@ | ||
|
||
// set up rate limiter: maximum of 100 requests per 15 minutes | ||
const limiter = rateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
// TODO: Update docs | ||
app.get(baseEndpoint + "/get", async function (req, res) { | ||
app.get(baseEndpoint + "/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.report, res, lang); | ||
@@ -54,3 +61,3 @@ | ||
|
||
app.post(baseEndpoint + "/create", async function (req, res) { | ||
app.post(baseEndpoint + "/create", limiter, async function (req, res) { | ||
isFeatureEnabled(features.report, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
|
||
try { | ||
function getVault(dbQuery) { | ||
db.query(dbQuery, function (error, results, fields) { |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we should use parameterized queries to safely embed the user input into the SQL query string. This approach ensures that the user input is treated as a literal value and not as part of the SQL command, thus preventing SQL injection attacks.
- Modify the
getVault
function to accept query parameters. - Use the query parameters in the SQL query instead of directly embedding the user input.
- Update the
db.query
call to use the parameterized query.
-
Copy modified lines R11-R12 -
Copy modified lines R38-R39 -
Copy modified line R44
@@ -10,4 +10,4 @@ | ||
try { | ||
function getVault(dbQuery) { | ||
db.query(dbQuery, function (error, results, fields) { | ||
function getVault(dbQuery, queryParams) { | ||
db.query(dbQuery, queryParams, function (error, results, fields) { | ||
console.log(results); | ||
@@ -37,4 +37,4 @@ | ||
if (vaultId) { | ||
let dbQuery = `SELECT * FROM vault WHERE vaultId=${vaultId};`; | ||
getVault(dbQuery); | ||
let dbQuery = `SELECT * FROM vault WHERE vaultId=?;`; | ||
getVault(dbQuery, [vaultId]); | ||
} | ||
@@ -43,3 +43,3 @@ | ||
let dbQuery = `SELECT * FROM vault ORDER BY position ASC;`; | ||
getVault(dbQuery); | ||
getVault(dbQuery, []); | ||
} catch (error) { |
app.post(baseEndpoint + "/create", async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
|
||
const actioningUser = required(req.body, "actioningUser", res); | ||
const displayName = required(req.body, "displayName", res); | ||
const description = required(req.body, "description", res); | ||
const redirectUrl = required(req.body, "redirectUrl", res); | ||
const position = required(req.body, "position", res); | ||
|
||
try { | ||
db.query( | ||
`INSERT INTO vault | ||
(displayName, description, redirectUrl, position) | ||
VALUES (?, ?, ?, ?)`, | ||
[ | ||
displayName, | ||
description, | ||
redirectUrl, | ||
position | ||
], | ||
function (error, results, fields) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
generateLog( | ||
actioningUser, | ||
"SUCCESS", | ||
"VAULT", | ||
`Created ${displayName}`, | ||
res | ||
); | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Created ${displayName} vault.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we will use the express-rate-limit
package to add rate limiting to the Express application. This will involve:
- Installing the
express-rate-limit
package. - Importing the package in the
api/routes/vault.js
file. - Setting up a rate limiter with appropriate configuration.
- Applying the rate limiter to the routes that perform database operations.
-
Copy modified line R2 -
Copy modified lines R6-R9 -
Copy modified line R11 -
Copy modified line R60 -
Copy modified line R112 -
Copy modified line R172
@@ -1,2 +1,3 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
@@ -4,4 +5,8 @@ | ||
const baseEndpoint = "/api/vault"; | ||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { | ||
app.get(baseEndpoint + "/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
@@ -54,3 +59,3 @@ | ||
|
||
app.post(baseEndpoint + "/create", async function (req, res) { | ||
app.post(baseEndpoint + "/create", limiter, async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
@@ -106,3 +111,3 @@ | ||
|
||
app.post(baseEndpoint + "/edit", async function (req, res) { | ||
app.post(baseEndpoint + "/edit", limiter, async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
@@ -166,3 +171,3 @@ | ||
|
||
app.post(baseEndpoint + "/delete", async function (req, res) { | ||
app.post(baseEndpoint + "/delete", limiter, async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
app.post(baseEndpoint + "/edit", async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
|
||
const actioningUser = required(req.body, "actioningUser", res); | ||
const vaultId = required(req.body, "vaultId", res); | ||
const displayName = required(req.body, "displayName", res); | ||
const description = required(req.body, "description", res); | ||
const redirectUrl = required(req.body, "redirectUrl", res); | ||
const position = required(req.body, "position", res); | ||
|
||
try { | ||
db.query( | ||
` | ||
UPDATE | ||
vault | ||
SET | ||
displayName=?, | ||
description=?, | ||
redirectUrl=?, | ||
position=? | ||
WHERE vaultId=?;`, | ||
[ | ||
displayName, | ||
description, | ||
redirectUrl, | ||
position, | ||
vaultId, | ||
], | ||
function (error, results, fields) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
generateLog( | ||
actioningUser, | ||
"SUCCESS", | ||
"VAULT", | ||
`Edited ${displayName}`, | ||
res | ||
); | ||
|
||
return res.send({ | ||
success: true, | ||
message: `${displayName} has been edited.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
app.post(baseEndpoint + "/delete", async function (req, res) { | ||
isFeatureEnabled(features.vault, res, lang); | ||
|
||
const actioningUser = required(req.body, "actioningUser", res); | ||
const vaultId = required(req.body, "vaultId", res); | ||
|
||
try { | ||
db.query( | ||
`DELETE FROM vault WHERE vaultId=?;`, | ||
[vaultId], | ||
function (error, results, fields) { | ||
if (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
generateLog( | ||
actioningUser, | ||
"WARNING", | ||
"VAULT", | ||
`Deleted ${vaultId}`, | ||
res | ||
); | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Deletion of vault with the id ${vaultId} has been successful.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we will introduce rate limiting to the Express application using the express-rate-limit
package. This will ensure that the number of requests to the endpoints is controlled, preventing potential DoS attacks.
- Install the
express-rate-limit
package if it is not already installed. - Import the
express-rate-limit
package in theapi/routes/vault.js
file. - Set up a rate limiter with appropriate configuration (e.g., maximum of 100 requests per 15 minutes).
- Apply the rate limiter to the routes that perform database access operations.
-
Copy modified line R2 -
Copy modified lines R7-R13
@@ -1,2 +1,3 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
@@ -5,2 +6,9 @@ | ||
|
||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
app.use(limiter); | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
app.post(baseEndpoint + "/clear", async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
|
||
try { | ||
db.query( | ||
`TRUNCATE bridge;`, | ||
function (error, results, fields) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Bridge has now been cleared.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
res.send({ | ||
success: false, | ||
message: `${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the route handlers that perform database access operations. The best way to achieve this is by using the express-rate-limit
middleware. This middleware allows us to set a maximum number of requests that can be made to the server within a specified time window. We will apply this middleware to the relevant routes to ensure that they are protected against denial-of-service attacks.
We will need to:
- Install the
express-rate-limit
package. - Import the
express-rate-limit
package in the file. - Set up a rate limiter with appropriate configuration.
- Apply the rate limiter to the relevant routes.
-
Copy modified line R2 -
Copy modified lines R6-R9 -
Copy modified line R11 -
Copy modified line R65 -
Copy modified line R99 -
Copy modified line R129 -
Copy modified line R193
@@ -1,2 +1,3 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
@@ -4,4 +5,8 @@ | ||
const baseEndpoint = "/api/bridge"; | ||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { | ||
app.get(baseEndpoint + "/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -59,3 +64,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/add", async function (req, res) { | ||
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -93,3 +98,3 @@ | ||
|
||
app.post(baseEndpoint + "/clear", async function (req, res) { | ||
app.post(baseEndpoint + "/clear", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -123,3 +128,3 @@ | ||
|
||
app.get(baseEndpoint + "/server/get", async function (req, res) { | ||
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -187,3 +192,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/process", async function (req, res) { | ||
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99) * Delete message after filtering prohibited content. * Fix spacing in network log messages. * Make usernames more presentable in logs. * Remove deleted channel field from being mentioned twice. * Fixed issue where filter errors after response is sent. * Changed from HEX to Colour * Add /poll command. * Add page descriptions to headers. * Added keywords and SEO option to configuration. * Add documentation badges for list and editors. * Push mobile view changes for session views. * Resolved mobile styling issues with dashboard views. * Added a staffChannel config option and a /staffhelp command * Resolve issues with cookie banner not showing on /register * Made urgent change to hasPermission, allowing non-logged in users to view admin panel. * Reformat all project files using Prettier. (#90) * Commit not found. * Prettify all JS and JSON files. * Resolve issue with logout crashing. * Separate redirect route into own file, add config option for kb and added issue tracker route. * Change node engine to support node 18. (#92) * Implementation of a Ranks/donation page. (#91) * Commence work on /ranks page and Tebex integration. * Transitioning back to JSON file, using catagory and packages * Finish rank page implementation. * Update perks. * Implement a call to action button style instead and make mobile friendly. * Made the server name look to site config for /ranks * Change rank page descriptor. * Commit start of rego process. * Add more routes * Implement 2fa interactive form element. * Install packages for email integration * Implement email template draft and smtp credentials. * Commence more work on controller and tests for emails. * Working on pathing. * Fix pathing on email template. * Add email header and footer and fix up routes. * Add a rough template draft of registration * Change registration gateway to discord, commence working on Minecraft link. * Add user verification via /verify * Remove all old rego code and mentions to passwords, remove email views and partials. * Add token code expiry and draft a expiry cron task. * Refactor getUser() into UserGetter * Push user verification service. * Commence drafting profiles and finalising login gateway * Add coming soon alerts on profile features. * Commit more profile work and db profile changes. * Applied permissions to profile. * Add example.env and config files. * Added Minecraft login and chat audits, also added website login. * Added discord voice and message audit events. * Filled in fields for audit to complete feature development. * Start work on profile editor. * Start implementing social connections into editor. * Finalise design for profile editor. * Implemented all of the base work for API routes and controllers. * Start on profile/display in editor and fix issue with Gravatar. * Finalise Social Connections in display and editor. * Fix permission node of everyone able to see dashboard, and open new tab for social connections. * Audit: If no data, then display no data instead of invalid date * Added profile stats for total logins and playtime. * Add latest session with online and offline indicators. * Add support for verification server in /server * Resolved issues with Server types displaying all instead of their type. * Create dbupgrade.sql Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql * Commence port to new schema. * Fix result type return in user api and added 17 global images. * Make unregistered failure link back to rego page. * Set audit to skip for discord voice and chat if discord is not linked. * Resolved issues with user api creation. * Resolve issues with messages attempting to send to channels. * Require the webhook package. * Rollback to d70b343 * Changes to user route and troubleshooting discord login. * Remove redirect returns. * Add troubleshooting to callback. * Push further troubleshooting. * Add troubleshooting to isRegistered * Add additional check and troubleshooting * Commit * Add a build command. * Fix Discord oAuth (#98) * Wrap in string for ID and secret. * Add logging to callback. * Add more logging. * Add more testing * got here marker. * move marker. * Move marker * update marker * marker 4, reveal session * Add permission data log * Fix issues with loading profile editor. * On profile updates, redirect to profile. * Add steam social and profanity filter to interests. * Add ability for linked accounts to not trigger linking codes. * Push profile command. * Add ranks api to fetch by rank and user. * Add debug for user permissions --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]> * Added rank permissions context into login sessions and clean up profile command. (#100) * Start rank perms scope on user implementation * Fix getUserPermissions to scope in rank permission nodes. * Remove the zanderdev prefix from permissions lookup. * Replace with amended getUserLastSession() to stop profiles from crashing. * Refactor to stop nulls from crashing the API * Removed all Craftatar discord side features due to traffic amplification attacks. * Add ` in profile title username to keep formatting. * Start work on report and locking behind login session. * Added report support via in-game and web. * Add discord /report command. * Add feature blocks to apply, ranks and report. Fix staffhelp command. * move reporting to true * Get a timeout on db and refactor to CraftHead. * Start draft implementation of shop directory * Start the bridge draft. * API routes and dashboard UI * bridge api and dashboard implementation * Have target server only execute non-processed tasks * Add a clean up task and don't execute old tasks. * Start work on shop directory api and website route. * Implement shopdirectory page, add by userId in users api and add /shop/get * Fix db merge issues * Replaced with prod implementation. * Push rate limiting on /shop/get * JSON parsing troubleshooting * Add ref to profile * Added WIP shop command. * defer response on shop * Fix undefined fields. * Prefer display name over item name. * Fix embed formatting issue on new line. * Fix up additional formatting in embed. * Remove $ from amount. * Remove $ form stock --------- Co-authored-by: Aron Brown <[email protected]> Co-authored-by: Ben Robson <[email protected]>
* Update dbinit.sql Add query to create a punishments view that pulls data from litebans. * Fix formatting in dbinit.sql
…into feat-bridge
try { | ||
function getReports(dbQuery) { | ||
return new Promise((resolve, reject) => { | ||
db.query(dbQuery, function (error, results, fields) { |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to ensure that user input is safely embedded into the SQL query. The best way to achieve this is by using query parameters or prepared statements. This approach ensures that the user input is treated as a literal value and not as part of the SQL query itself.
In this specific case, we will modify the getReports
function to use query parameters for the reportedId
value. This will involve changing the SQL query string to use a placeholder for the reportedId
and passing the actual value as a parameter to the db.query
function.
-
Copy modified line R14 -
Copy modified line R16 -
Copy modified lines R40-R41
@@ -13,5 +13,5 @@ | ||
try { | ||
function getReports(dbQuery) { | ||
function getReports(dbQuery, params = []) { | ||
return new Promise((resolve, reject) => { | ||
db.query(dbQuery, function (error, results, fields) { | ||
db.query(dbQuery, params, function (error, results, fields) { | ||
if (error) { | ||
@@ -39,4 +39,4 @@ | ||
if (reportedId) { | ||
let dbQuery = `SELECT * FROM reports WHERE reportedId=${reportedId};`; | ||
await getReports(dbQuery); | ||
let dbQuery = `SELECT * FROM reports WHERE reportedId=?;`; | ||
await getReports(dbQuery, [reportedId]); | ||
} |
try { | ||
async function getShops(dbQuery) { | ||
return new Promise((resolve, reject) => { | ||
db.query(dbQuery, async (error, results) => { |
Check failure
Code scanning / CodeQL
Database query built from user-controlled sources High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we should use query parameters to safely embed the user input into the SQL query. This approach prevents SQL injection by ensuring that the user input is treated as a literal value rather than executable code.
- Modify the construction of the
dbQuery
string to use parameterized queries. - Use the
db.query
method's parameterization feature to pass the user input as a parameter to the query. - Update the
getShops
function to accept query parameters and pass them to thedb.query
method.
-
Copy modified line R15 -
Copy modified line R17 -
Copy modified line R120 -
Copy modified line R122 -
Copy modified line R125
@@ -14,5 +14,5 @@ | ||
try { | ||
async function getShops(dbQuery) { | ||
async function getShops(dbQuery, queryParams) { | ||
return new Promise((resolve, reject) => { | ||
db.query(dbQuery, async (error, results) => { | ||
db.query(dbQuery, queryParams, async (error, results) => { | ||
if (error) { | ||
@@ -119,7 +119,8 @@ | ||
const dbQuery = material | ||
? `SELECT * FROM shoppingDirectory WHERE item LIKE '%${material}%';` | ||
? `SELECT * FROM shoppingDirectory WHERE item LIKE $1;` | ||
: `SELECT * FROM shoppingDirectory;`; | ||
const queryParams = material ? [`%${material}%`] : []; | ||
|
||
// Execute the query and process the shops | ||
await getShops(dbQuery); | ||
await getShops(dbQuery, queryParams); | ||
} catch (error) { |
api/routes/bridge.js
Outdated
app.post(baseEndpoint + "/server/update", async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
|
||
const serverInfo = required(req.body, "serverInfo", res); | ||
let lastUpdated = required(req.body, "lastUpdated", res); | ||
|
||
try { | ||
const serverInfoString = JSON.stringify(serverInfo); | ||
|
||
db.query( | ||
`UPDATE serverStatus SET statusInfo = ?, lastUpdated = ? WHERE serverStatusId = 1;`, | ||
[serverInfoString, lastUpdated], | ||
function (error, updateResults) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `Update failed: ${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
message: `Server status updated successfully.`, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
return res.send({ | ||
success: false, | ||
message: `Unexpected error: ${error}`, | ||
}); | ||
} | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the Express application. The best way to do this is by using the express-rate-limit
package, which allows us to easily set up and apply rate limiting to our routes. We will configure a rate limiter and apply it to the routes that perform database access operations.
- Install the
express-rate-limit
package. - Import the
express-rate-limit
package in the file. - Configure a rate limiter with appropriate settings (e.g., maximum number of requests per time window).
- Apply the rate limiter to the relevant routes.
-
Copy modified line R2 -
Copy modified lines R7-R13 -
Copy modified line R67 -
Copy modified line R101 -
Copy modified line R131 -
Copy modified line R161 -
Copy modified line R195
@@ -1,2 +1,3 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import RateLimit from 'express-rate-limit'; | ||
|
||
@@ -5,3 +6,9 @@ | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { | ||
// set up rate limiter: maximum of 100 requests per 15 minutes | ||
const limiter = RateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // max 100 requests per windowMs | ||
}); | ||
|
||
app.get(baseEndpoint + "/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -59,3 +66,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/add", async function (req, res) { | ||
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -93,3 +100,3 @@ | ||
|
||
app.post(baseEndpoint + "/clear", async function (req, res) { | ||
app.post(baseEndpoint + "/clear", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -123,3 +130,3 @@ | ||
|
||
app.get(baseEndpoint + "/server/get", async function (req, res) { | ||
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -153,3 +160,3 @@ | ||
|
||
app.post(baseEndpoint + "/server/update", async function (req, res) { | ||
app.post(baseEndpoint + "/server/update", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
@@ -187,3 +194,3 @@ | ||
|
||
app.post(baseEndpoint + "/command/process", async function (req, res) { | ||
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
app.get(baseEndpoint + "/server/get", async function (req, res) { | ||
isFeatureEnabled(features.bridge, res, lang); | ||
|
||
try { | ||
db.query( | ||
`SELECT * FROM serverStatus;`, | ||
function (error, results) { | ||
if (error) { | ||
return res.send({ | ||
success: false, | ||
message: `Failed: ${error}`, | ||
}); | ||
} | ||
|
||
return res.send({ | ||
success: true, | ||
data: results, | ||
}); | ||
} | ||
); | ||
} catch (error) { | ||
return res.send({ | ||
success: false, | ||
message: `Unexpected error: ${error}`, | ||
}); | ||
} | ||
|
||
return res; | ||
}); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
a database access
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 3 months ago
To fix the problem, we need to introduce rate limiting to the route handlers in the bridgeApiRoute
function. The best way to achieve this is by using the express-rate-limit
middleware. This middleware allows us to set a maximum number of requests that can be made to the server within a specified time window. We will apply this middleware to all the routes defined in the bridgeApiRoute
function.
- Install the
express-rate-limit
package if it is not already installed. - Import the
express-rate-limit
package at the beginning of the file. - Define a rate limiter with appropriate settings (e.g., maximum of 100 requests per 15 minutes).
- Apply the rate limiter to the routes in the
bridgeApiRoute
function.
-
Copy modified line R2 -
Copy modified lines R5-R8 -
Copy modified lines R11-R12
@@ -1,6 +1,13 @@ | ||
import { isFeatureEnabled, required, optional, generateLog } from "../common"; | ||
import rateLimit from 'express-rate-limit'; | ||
|
||
export default function bridgeApiRoute(app, config, db, features, lang) { | ||
const limiter = rateLimit({ | ||
windowMs: 15 * 60 * 1000, // 15 minutes | ||
max: 100, // limit each IP to 100 requests per windowMs | ||
}); | ||
const baseEndpoint = "/api/bridge"; | ||
|
||
app.use(baseEndpoint, limiter); | ||
|
||
app.get(baseEndpoint + "/get", async function (req, res) { |
-
Copy modified lines R52-R53
@@ -51,3 +51,4 @@ | ||
"querystring": "^0.2.1", | ||
"zero-md": "^2.3.1" | ||
"zero-md": "^2.3.1", | ||
"express-rate-limit": "^7.4.1" | ||
} |
Package | Version | Security advisories |
express-rate-limit (npm) | 7.4.1 | None |
No description provided.