Conversation
update jon snow
update env variables
Login bug
impliment middleware to prevent xss attacks
undo xss middleware
Ncpdp integration
Intermediary ncpdp
| await axios.post(endpoint, rxFill, { | ||
| headers: { 'Content-Type': 'application/xml' } | ||
| }); |
Check failure
Code scanning / CodeQL
Server-side request forgery
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
To fix the problem, user input must not be allowed to arbitrarily control the hostname/URL used in outgoing requests. Instead, configuration updates from /api/config should either (a) not be allowed to change network endpoints at all, or (b) be strictly validated against an allow‑list or strong URL/host constraints before being stored and later used in getRxFillEndpoint().
The least intrusive and safest fix, without changing overall behavior, is:
-
In
backend/src/lib/pharmacyConfig.js:- Add a helper
sanitizeUrlthat:- Uses the built‑in
URLclass to parse a candidate URL. - Enforces that protocol is
http:orhttps:. - Enforces that hostname is within a small, explicit allow‑list (e.g., set from environment variables, which are assumed trusted).
- Returns either the validated URL string or
null/the previous value if invalid.
- Uses the built‑in
- Add an
applyConfigUpdatefunction that:- Starts from the existing
config. - For each updatable key (
useIntermediary,intermediaryUrl,remsAdminUrl,ehrUrl), validates and normalizes the value. - For URL fields, calls
sanitizeUrland only updates if it passes validation; otherwise, keeps the previous value.
- Starts from the existing
- Update
updateConfig(newConfig)to callapplyConfigUpdateinstead of spreadingnewConfigblindly intoconfig.
- Add a helper
-
In
backend/src/routes/doctorOrders.js:- Leave the use of
getRxFillEndpoint()andaxios.post(endpoint, ...)as‑is; they will now only ever use validated URLs.
- Leave the use of
This maintains the external API (clients can still POST config changes), but ensures that only safe, pre‑approved endpoints can be set, preventing an attacker from directing the server to arbitrary hosts.
| const response = await axios.post( | ||
| endpoint, | ||
| initiationRequest, | ||
| { | ||
| headers: { | ||
| Accept: 'application/xml', | ||
| 'Content-Type': 'application/xml' | ||
| } | ||
| } | ||
| ); |
Check failure
Code scanning / CodeQL
Server-side request forgery
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
In general, to fix SSRF issues where URLs are derived from user input, you must prevent arbitrary hostnames/URLs from being configured. Typical mitigations are: (1) strict validation and normalization of the configured URLs, (2) allow‑listing hosts or base URLs, and optionally (3) blocking private/loopback IPs in dynamic URLs.
For this case, the best fix with minimal behavior change is to constrain what can be written into the config object via /api/config. We can add a helper in pharmacyConfig.js that sanitizes/validates newConfig before merging: it should accept only known keys (e.g., useIntermediary, intermediaryUrl, remsAdminUrl, ehrUrl), enforce types, and validate URL fields with the built‑in URL class. Optionally, it can also enforce that hosts belong to an allowed set or at least are not localhost or private IPs. Then we modify updateConfig to call this validator and merge only the sanitized values. No changes are needed in sendREMSInitiationRequest itself, since it will now only ever get safe endpoints from getNCPDPEndpoint().
Concretely:
- In
backend/src/lib/pharmacyConfig.js, introduce asanitizeConfigUpdate(newConfig)function (aboveupdateConfig) that:- Creates a new object.
- If
useIntermediaryis present, coerces it to a boolean (or keeps it if already boolean). - For each of
intermediaryUrl,remsAdminUrl,ehrUrlpresent innewConfig, verifies:- It is a string.
- It parses as an absolute URL via
new URL(value). - Optionally, checks host against a simple allowlist or at least disallows
localhost,127.0.0.1,::1, etc.
- Returns the sanitized object.
- Change
updateConfigso that instead ofconfig = { ...config, ...newConfig };it doesconst safeUpdate = sanitizeConfigUpdate(newConfig); config = { ...config, ...safeUpdate };. - No changes are required in
backend/src/routes/doctorOrders.jsfor this particular SSRF path.
This keeps existing configuration semantics (same keys, same endpoints) but prevents arbitrary unvalidated URLs from being injected through /api/config.
| const response = await axios.post( | ||
| endpoint, | ||
| remsRequest, | ||
| { | ||
| headers: { | ||
| Accept: 'application/xml', | ||
| 'Content-Type': 'application/xml' | ||
| } | ||
| } | ||
| ); |
Check failure
Code scanning / CodeQL
Server-side request forgery
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
In general, to fix SSRF in this pattern you must stop using arbitrary client-provided URLs as HTTP targets. Instead, only allow safe, validated values (for example, selecting from an allow-list of hosts or validating that provided URLs meet strict criteria and do not point to internal or unsupported schemes).
For this codebase, the minimal, non‑breaking fix is to validate and sanitize any configuration fields that influence outbound URLs (intermediaryUrl, remsAdminUrl, ehrUrl) when updateConfig merges req.body into config. We can implement a local sanitizeConfig helper in pharmacyConfig.js that:
- Ensures
useIntermediaryis boolean. - Validates that each URL, if provided, is a well-formed HTTP(S) URL using Node’s
URLclass. - Rejects URLs with non-
http/httpsprotocols. - Rejects obviously unsafe hosts such as
localhost,127.0.0.1, and other loopback forms (to mitigate SSRF to local services). - Optionally strips trailing slashes to keep existing behavior stable, but still returns the same endpoints for valid values.
updateConfig will then apply this sanitizer before updating the global config object. The route handler in doctorOrders.js can stay the same, since updateConfig will enforce constraints centrally. No changes to sendREMSRequest are needed, as it will now always receive a vetted URL from getNCPDPEndpoint. All edits are confined to backend/src/lib/pharmacyConfig.js.
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
devnot main (the only exception to this is releases fromdevand hotfix branches)Checklist for conducting a review
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.