Skip to content
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

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 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
6 changes: 5 additions & 1 deletion api/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,20 +220,24 @@ export async function setBannerCookie(alertType, alertContent, res) {
res.setCookie("alertType", alertType, {
path: "/",
expires: expiryTime,
httpOnly: true,
});

// Set Content Type
res.setCookie("alertContent", alertContent, {
path: "/",
expires: expiryTime,
httpOnly: true,
});

return true;
// Make sure to send the res
return res;
} catch (error) {
console.log(error);
}
}


/*
Sets two cookies (alertType and alertContent) with specified values and an expiration time of one second.
These cookies are set on the root path and are returned by the function.
Expand Down
23 changes: 23 additions & 0 deletions api/internal_redirect/bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { hasPermission, postAPIRequest } from "../common";

export default function bridgeRedirectRoute(app, config, lang) {
const baseEndpoint = "/redirect/bridge";

app.post(baseEndpoint + "/command/add", async function (req, res) {
if (!hasPermission("zander.web.bridge", req, res)) return;

// Add userId to req.body
req.body.actioningUser = req.session.user.userId;

postAPIRequest(
`${process.env.siteAddress}/api/bridge/command/add`,
req.body,
`${process.env.siteAddress}/dashboard/bridge`,
res
);

res.redirect(`${process.env.siteAddress}/dashboard/bridge`);

return res;
});
}
6 changes: 6 additions & 0 deletions api/internal_redirect/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import applicationRedirectRoute from "./application";
import serverRedirectRoute from "./server";
import webRedirectRoute from "./web";
import announcementsRedirectRoute from "./announcement";
import reportRedirectRoute from "./report";
import vaultRedirectRoute from "./vault";
import bridgeRedirectRoute from "./bridge";

export default (app, config, lang) => {
applicationRedirectRoute(app, config, lang);
serverRedirectRoute(app, config, lang);
reportRedirectRoute(app, config, lang);
webRedirectRoute(app, config, lang);
announcementsRedirectRoute(app, config, lang);
vaultRedirectRoute(app, config, lang);
bridgeRedirectRoute(app, config, lang);
};
20 changes: 20 additions & 0 deletions api/internal_redirect/report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { hasPermission, postAPIRequest } from "../common";

export default function reportRedirectRoute(app, config, lang) {
const baseEndpoint = "/redirect/report";

app.post(baseEndpoint + "/create", async function (req, res) {
req.body.reporterUser = req.session.user.username;

postAPIRequest(
`${process.env.siteAddress}/api/report/create`,
req.body,
`${process.env.siteAddress}/report`,
res
);

res.redirect(`${process.env.siteAddress}/`);

return res;
});
}
59 changes: 59 additions & 0 deletions api/internal_redirect/vault.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { hasPermission, postAPIRequest } from "../common";

export default function vaultRedirectRoute(app, config, lang) {
const baseEndpoint = "/redirect/vault";

app.post(baseEndpoint + "/create", async function (req, res) {
if (!hasPermission("zander.web.vault", req, res)) return;

// Add userId to req.body
req.body.actioningUser = req.session.user.userId;

postAPIRequest(
`${process.env.siteAddress}/api/vault/create`,
req.body,
`${process.env.siteAddress}/dashboard/vault`,
res
);

res.redirect(`${process.env.siteAddress}/dashboard/vault`);

return res;
});

app.post(baseEndpoint + "/edit", async function (req, res) {
if (!hasPermission("zander.web.vault", req, res)) return;

// Add userId to req.body
req.body.actioningUser = req.session.user.userId;

postAPIRequest(
`${process.env.siteAddress}/api/vault/edit`,
req.body,
`${process.env.siteAddress}/dashboard/vault`,
res
);

res.redirect(`${process.env.siteAddress}/dashboard/vault`);

return res;
});

app.post(baseEndpoint + "/delete", async function (req, res) {
if (!hasPermission("zander.web.vault", req, res)) return;

// Add userId to req.body
req.body.actioningUser = req.session.user.userId;

postAPIRequest(
`${process.env.siteAddress}/api/vault/delete`,
req.body,
`${process.env.siteAddress}/dashboard/vault`,
res
);

res.redirect(`${process.env.siteAddress}/dashboard/vault`);

return res;
});
}
18 changes: 9 additions & 9 deletions api/routes/announcement.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

app.get(baseEndpoint + "/get", async function (req, res) {
isFeatureEnabled(features.announcements, res, lang);
const announcementId = optional(req.query, "id");
const announcementId = optional(req.query, "announcementId");
const announcementType = optional(req.query, "announcementType");
const enabled = optional(req.query, "enabled");

try {
function getAnnouncements(dbQuery) {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.
if (error) {
return res.send({
success: false,
Expand Down Expand Up @@ -157,14 +157,14 @@
try {
db.query(
`
UPDATE announcements
SET
enabled=?,
announcementType=?,
body=?,
colourMessageFormat=?,
link=?
WHERE announcementId=?;`,
UPDATE announcements
SET
enabled=?,
announcementType=?,
body=?,
colourMessageFormat=?,
link=?
WHERE announcementId=?;`,
[
enabled,
announcementType,
Expand Down
2 changes: 1 addition & 1 deletion api/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

app.get(baseEndpoint + "/get", async function (req, res) {
isFeatureEnabled(features.applications, res, lang);
const applicationId = optional(req.query, "applicationId");
const applicationId = optional(req.query, "id");

try {
function getApplications(dbQuery) {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.
console.log(results);

if (error) {
Expand Down
196 changes: 196 additions & 0 deletions api/routes/bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";

export default function bridgeApiRoute(app, config, db, features, lang) {
const baseEndpoint = "/api/bridge";

app.get(baseEndpoint + "/get", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
const bridgeId = optional(req.query, "id");
const targetServer = optional(req.query, "targetServer");

try {
function getBridge(dbQuery) {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.
This query string depends on a
user-provided value
.

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.

  1. Modify the getBridge function to accept query parameters.
  2. Update the SQL query strings to use placeholders for the parameters.
  3. Pass the user-provided data as parameters to the db.query function.
Suggested changeset 1
api/routes/bridge.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/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -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) {
EOF
@@ -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) {
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if (error) {
res.send({
success: false,
message: `${error}`,
});
}

if (!results) {
return res.send({
success: false,
message: `No Bridge requests can be found`,
});
}

return res.send({
success: true,
data: results,
});
});
}

// Get Bridge by ID
if (bridgeId) {
let dbQuery = `SELECT * FROM bridge WHERE bridgeId=${bridgeId};`;
getBridge(dbQuery);
}

// Get Bridge by Targeted Server
if (targetServer) {
let dbQuery = `SELECT * FROM bridge WHERE targetServer='${targetServer}' AND processed=0;`;
getBridge(dbQuery);
}

// Return all Bridge requests by default
let dbQuery = `SELECT * FROM bridge;`;
getBridge(dbQuery);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

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;
});
Comment on lines +60 to +92

Check failure

Code scanning / CodeQL

Missing rate limiting High

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

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:

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Set up a rate limiter with appropriate configuration.
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.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/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -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);
EOF
@@ -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);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

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;
});
Comment on lines +94 to +122

Check failure

Code scanning / CodeQL

Missing rate limiting High

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

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:

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Set up a rate limiter with appropriate configuration.
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.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/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -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);
EOF
@@ -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);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

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

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

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.

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Configure a rate limiter with appropriate settings (e.g., maximum number of requests per time window).
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.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/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -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);
EOF
@@ -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);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

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

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

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.

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the api/routes/bridge.js file.
  3. Set up a rate limiter with appropriate configuration (e.g., maximum number of requests per time window).
  4. Apply the rate limiter to the routes that perform database access operations.
Suggested changeset 2
api/routes/bridge.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/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -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);
EOF
@@ -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);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
}
Loading