Skip to content

Conversation

@smalho01
Copy link
Contributor

Describe your changes

Please include a summary of the changes and the related issue/task. Please also include relevant motivation and context. List any dependencies that are required for this change, including links to other pull requests/branches in other repositories if applicable.

Issue ticket number and Jira link

Please include the Jira Ticket Number and Link for this issue/task.

Checklist before requesting a review

  • I have performed a self-review of my code
  • Ensure the target / base branch for any feature PR is set to dev not main (the only exception to this is releases from dev and hotfix branches)

Checklist for conducting a review

  • Review the code changes and make sure they all make sense and are necessary.
  • Pull the PR branch locally and test by running through workflow and making sure everything works as it is supposed to.

Workflow

Owner of the Pull Request will be responsible for merge after all requirements are met, including approval from at least one reviewer. Additional changes made after a review will dismiss any approvals and require re-review of the additional updates. Auto merging can be enabled below if additional changes are likely not to be needed. The bot will auto assign reviewers to your Pull Request for you.

Comment on lines 157 to 220
const order = await doctorOrder.findById(req.params.id).exec();
console.log('Found doctor order by id! --- ', order);

// Non-REMS drugs auto-approve
if (!isRemsDrug(order)) {
const newOrder = await doctorOrder.findOneAndUpdate(
{ _id: req.params.id },
{ dispenseStatus: 'Approved' },
{ new: true }
);
res.send(newOrder);
console.log('Non-REMS drug - auto-approved');
return;
}

// REMS drugs - send NCPDP REMSRequest per spec
console.log('REMS drug - sending REMSRequest for authorization per NCPDP workflow');
const ncpdpResponse = await sendREMSRequest(order);

if (!ncpdpResponse) {
res.send(order);
console.log('NCPDP REMSRequest failed');
return;
}

// Update based on NCPDP response
const updateData = {
dispenseStatus: getDispenseStatus(order, ncpdpResponse),
metRequirements: ncpdpResponse.metRequirements || order.metRequirements
};

if (ncpdpResponse.status === 'APPROVED') {
updateData.authorizationNumber = ncpdpResponse.authorizationNumber;
updateData.authorizationExpiration = ncpdpResponse.authorizationExpiration;
updateData.caseNumber = ncpdpResponse.caseId;

// Format approval note with ETASU summary
let approvalNote = `APPROVED - Authorization: ${ncpdpResponse.authorizationNumber}, Expires: ${ncpdpResponse.authorizationExpiration}`;
if (ncpdpResponse.etasuSummary) {
approvalNote += `\n\nETASU Requirements Met:\n${ncpdpResponse.etasuSummary}`;
}
updateData.remsNote = approvalNote;
updateData.denialReasonCode = null;
console.log('APPROVED:', ncpdpResponse.authorizationNumber);
} else if (ncpdpResponse.status === 'DENIED') {
updateData.denialReasonCode = ncpdpResponse.reasonCode;
updateData.remsNote = ncpdpResponse.remsNote;
updateData.caseNumber = ncpdpResponse.caseId;
console.log('DENIED:', ncpdpResponse.reasonCode);
}

const newOrder = await doctorOrder.findOneAndUpdate(
{ _id: req.params.id },
updateData,
{ new: true }
);

res.send(newOrder);
console.log('Updated order with NCPDP response');
} catch (error) {
console.log('Error', error);
return error;
}
});

/**

Check failure

Code scanning / CodeQL

Missing rate limiting High

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

Copilot Autofix

AI 1 day ago

In general, to fix missing rate limiting for expensive handlers in an Express app, you add a rate-limiting middleware (for example from express-rate-limit) and apply it either globally or to specific sensitive routes. This middleware counts requests per client (typically by IP) within a time window and rejects or delays requests that exceed a configured threshold, mitigating DoS via request floods.

For this file, the least intrusive, functionality-preserving fix is to introduce a small, dedicated rate limiter and apply it to the /api/updateRx/:id route (and optionally to the other DB-heavy routes if desired). We'll import express-rate-limit, define a limiter instance near the top of doctorOrders.js, and then pass it as middleware to router.patch('/api/updateRx/:id', ...). This only affects how many times the endpoint can be hit per client in a given window; it does not change the DB logic, request/response shapes, or route signatures.

Concretely:

  • At the top of backend/src/routes/doctorOrders.js, add import rateLimit from 'express-rate-limit';.
  • Define a limiter, e.g. const updateRxLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }); (values can be tuned; we just need reasonable protection).
  • Update the route definition on line 154 from router.patch('/api/updateRx/:id', async (req, res) => { ... to router.patch('/api/updateRx/:id', updateRxLimiter, async (req, res) => { ... so all accesses to this DB-intensive handler are throttled.

This single limiter instance addresses all three alert variants, since they all refer to DB calls within the same handler.

Suggested changeset 2
backend/src/routes/doctorOrders.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/backend/src/routes/doctorOrders.js b/backend/src/routes/doctorOrders.js
--- a/backend/src/routes/doctorOrders.js
+++ b/backend/src/routes/doctorOrders.js
@@ -16,7 +16,14 @@
 } from '../ncpdpScriptBuilder/buildScript.v2017071.js';
 import { NewRx } from '../database/schemas/newRx.js';
 import { medicationRequestToRemsAdmins } from '../database/data.js';
+import rateLimit from 'express-rate-limit';
 
+// Rate limiter for updateRx route to protect DB and external integrations
+const updateRxLimiter = rateLimit({
+  windowMs: 15 * 60 * 1000, // 15 minutes
+  max: 100,                 // limit each IP to 100 update requests per window
+});
+
 bpx(bodyParser);
 router.use(
   bodyParser.xml({
@@ -151,7 +157,7 @@
  * Route: 'doctorOrders/api/updateRx/:id'
  * Description : 'Updates prescription based on mongo id, sends NCPDP REMSRequest for authorization'
  */
-router.patch('/api/updateRx/:id', async (req, res) => {
+router.patch('/api/updateRx/:id', updateRxLimiter, async (req, res) => {
   try {
     const order = await doctorOrder.findById(req.params.id).exec();
     console.log('Found doctor order by id! --- ', order);
EOF
@@ -16,7 +16,14 @@
} from '../ncpdpScriptBuilder/buildScript.v2017071.js';
import { NewRx } from '../database/schemas/newRx.js';
import { medicationRequestToRemsAdmins } from '../database/data.js';
import rateLimit from 'express-rate-limit';

// Rate limiter for updateRx route to protect DB and external integrations
const updateRxLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 update requests per window
});

bpx(bodyParser);
router.use(
bodyParser.xml({
@@ -151,7 +157,7 @@
* Route: 'doctorOrders/api/updateRx/:id'
* Description : 'Updates prescription based on mongo id, sends NCPDP REMSRequest for authorization'
*/
router.patch('/api/updateRx/:id', async (req, res) => {
router.patch('/api/updateRx/:id', updateRxLimiter, async (req, res) => {
try {
const order = await doctorOrder.findById(req.params.id).exec();
console.log('Found doctor order by id! --- ', order);
backend/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/backend/package.json b/backend/package.json
--- a/backend/package.json
+++ b/backend/package.json
@@ -13,7 +13,8 @@
     "mongoose": "^8.9.5",
     "var": "^0.4.0",
     "web-vitals": "^2.1.4",
-    "xml2js": "^0.6.0"
+    "xml2js": "^0.6.0",
+    "express-rate-limit": "^8.2.1"
   },
   "devDependencies": {
     "@types/chai": "^4.3.4",
EOF
@@ -13,7 +13,8 @@
"mongoose": "^8.9.5",
"var": "^0.4.0",
"web-vitals": "^2.1.4",
"xml2js": "^0.6.0"
"xml2js": "^0.6.0",
"express-rate-limit": "^8.2.1"
},
"devDependencies": {
"@types/chai": "^4.3.4",
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 8.2.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines 167 to 207
res.send(newOrder);
console.log('Non-REMS drug - auto-approved');
return;
}

// REMS drugs - send NCPDP REMSRequest per spec
console.log('REMS drug - sending REMSRequest for authorization per NCPDP workflow');
const ncpdpResponse = await sendREMSRequest(order);

if (!ncpdpResponse) {
res.send(order);
console.log('NCPDP REMSRequest failed');
return;
}

// Update based on NCPDP response
const updateData = {
dispenseStatus: getDispenseStatus(order, ncpdpResponse),
metRequirements: ncpdpResponse.metRequirements || order.metRequirements
};

if (ncpdpResponse.status === 'APPROVED') {
updateData.authorizationNumber = ncpdpResponse.authorizationNumber;
updateData.authorizationExpiration = ncpdpResponse.authorizationExpiration;
updateData.caseNumber = ncpdpResponse.caseId;

// Format approval note with ETASU summary
let approvalNote = `APPROVED - Authorization: ${ncpdpResponse.authorizationNumber}, Expires: ${ncpdpResponse.authorizationExpiration}`;
if (ncpdpResponse.etasuSummary) {
approvalNote += `\n\nETASU Requirements Met:\n${ncpdpResponse.etasuSummary}`;
}
updateData.remsNote = approvalNote;
updateData.denialReasonCode = null;
console.log('APPROVED:', ncpdpResponse.authorizationNumber);
} else if (ncpdpResponse.status === 'DENIED') {
updateData.denialReasonCode = ncpdpResponse.reasonCode;
updateData.remsNote = ncpdpResponse.remsNote;
updateData.caseNumber = ncpdpResponse.caseId;
console.log('DENIED:', ncpdpResponse.reasonCode);
}

const newOrder = await doctorOrder.findOneAndUpdate(
{ _id: req.params.id },

Check failure

Code scanning / CodeQL

Missing rate limiting High

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

Copilot Autofix

AI 1 day ago

In general, the problem is fixed by adding a rate-limiting middleware to the route (or router) so that repeated requests from a client within a short time window are rejected or delayed. For Express, a common approach is to use the express-rate-limit package and apply a limiter specifically to sensitive routes that perform expensive DB operations or external HTTP calls.

The best fix here, without changing existing behavior beyond limiting abuse, is to import express-rate-limit, define a limiter tailored for doctor order–related operations, and apply it to the PATCH /api/updateRx/:id/pickedUp route. This keeps the current route logic intact while ensuring that a single client cannot flood this endpoint. Concretely, in backend/src/routes/doctorOrders.js we should: (1) add an import of express-rate-limit near the top, (2) define a limiter (e.g., window of 15 minutes and a reasonable max number of requests, such as 100) after the other middleware setup, and (3) modify the route definition on line 250 so that the limiter is passed as a middleware before the async handler: router.patch('/api/updateRx/:id/pickedUp', pickedUpLimiter, async (req, res) => { ... });. No other functionality inside the handler needs to change.

Suggested changeset 2
backend/src/routes/doctorOrders.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/backend/src/routes/doctorOrders.js b/backend/src/routes/doctorOrders.js
--- a/backend/src/routes/doctorOrders.js
+++ b/backend/src/routes/doctorOrders.js
@@ -16,7 +16,13 @@
 } from '../ncpdpScriptBuilder/buildScript.v2017071.js';
 import { NewRx } from '../database/schemas/newRx.js';
 import { medicationRequestToRemsAdmins } from '../database/data.js';
+import rateLimit from 'express-rate-limit';
 
+const pickedUpLimiter = rateLimit({
+  windowMs: 15 * 60 * 1000, // 15 minutes
+  max: 100, // limit each IP to 100 requests per windowMs for this route
+});
+
 bpx(bodyParser);
 router.use(
   bodyParser.xml({
@@ -247,7 +252,7 @@
  * Route: 'doctorOrders/api/updateRx/:id/pickedUp'
  * Description : 'Updates prescription dispense status to picked up and sends RxFill per NCPDP spec'
  */
-router.patch('/api/updateRx/:id/pickedUp', async (req, res) => {
+router.patch('/api/updateRx/:id/pickedUp', pickedUpLimiter, async (req, res) => {
   let prescriberOrderNumber = null;
   try {
     const newOrder = await doctorOrder.findOneAndUpdate(
EOF
@@ -16,7 +16,13 @@
} from '../ncpdpScriptBuilder/buildScript.v2017071.js';
import { NewRx } from '../database/schemas/newRx.js';
import { medicationRequestToRemsAdmins } from '../database/data.js';
import rateLimit from 'express-rate-limit';

const pickedUpLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs for this route
});

bpx(bodyParser);
router.use(
bodyParser.xml({
@@ -247,7 +252,7 @@
* Route: 'doctorOrders/api/updateRx/:id/pickedUp'
* Description : 'Updates prescription dispense status to picked up and sends RxFill per NCPDP spec'
*/
router.patch('/api/updateRx/:id/pickedUp', async (req, res) => {
router.patch('/api/updateRx/:id/pickedUp', pickedUpLimiter, async (req, res) => {
let prescriberOrderNumber = null;
try {
const newOrder = await doctorOrder.findOneAndUpdate(
backend/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/backend/package.json b/backend/package.json
--- a/backend/package.json
+++ b/backend/package.json
@@ -13,7 +13,8 @@
     "mongoose": "^8.9.5",
     "var": "^0.4.0",
     "web-vitals": "^2.1.4",
-    "xml2js": "^0.6.0"
+    "xml2js": "^0.6.0",
+    "express-rate-limit": "^8.2.1"
   },
   "devDependencies": {
     "@types/chai": "^4.3.4",
EOF
@@ -13,7 +13,8 @@
"mongoose": "^8.9.5",
"var": "^0.4.0",
"web-vitals": "^2.1.4",
"xml2js": "^0.6.0"
"xml2js": "^0.6.0",
"express-rate-limit": "^8.2.1"
},
"devDependencies": {
"@types/chai": "^4.3.4",
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 8.2.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants