/

CVE-2026-103938

Severity:

HIGH RISK

(7.1)

Cross-Site Request Forgery (CWE-352) in OpenEMR POS

CVE-2026-103938

Received

Vulnerability type

Category:

Cross-Site Request Forgery (CSRF)

CWE:

CWE-352

Impact:

Unauthorized changes to checkout and invoice state

Severity:

HIGH RISK

(7.1)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

OpenEMR's POS checkout interface accepts state-changing requests without consistently validating a CSRF token. If an authenticated billing user visits a malicious page while signed in, a cross-site request may void checkouts or regenerate invoice counters.

OpenEMR's POS checkout interface accepts state-changing requests without consistently validating a CSRF token. If an authenticated billing user visits a malicious page while signed in, a cross-site request may void checkouts or regenerate invoice counters.

Affected context

The issue occurs in OpenEMR's interface/patient_file/pos_checkout_ippf.php handling of the void, voidall, and regen operations. Risk exists when an authenticated billing user's browser can reach the interface and the request is processed without validating a CSRF token; the form_checksum check can be skipped when that parameter is omitted.

The issue occurs in OpenEMR's interface/patient_file/pos_checkout_ippf.php handling of the void, voidall, and regen operations. Risk exists when an authenticated billing user's browser can reach the interface and the request is processed without validating a CSRF token; the form_checksum check can be skipped when that parameter is omitted.

Exploit preconditions

  • Attack surface: The POS checkout interface in the affected application.
  • Required access: The victim must be authenticated as a billing user with access to the relevant operations.
  • Trigger point: The victim's browser sends a cross-site GET request while their authenticated session is active.
  • Why exploitation is possible: State-changing operations are available through GET requests, and CSRF validation can be bypassed when the optional checksum parameter is absent.
  • Attack surface: The POS checkout interface in the affected application.
  • Required access: The victim must be authenticated as a billing user with access to the relevant operations.
  • Trigger point: The victim's browser sends a cross-site GET request while their authenticated session is active.
  • Why exploitation is possible: State-changing operations are available through GET requests, and CSRF validation can be bypassed when the optional checksum parameter is absent.

Why this happens

The application performs state-changing operations through GET requests without requiring consistent CSRF token validation. Because the form_checksum integrity check is conditional, an omitted parameter can leave the request unverified. This is CWE-352: Cross-Site Request Forgery, where an application relies on a victim's authenticated browser to accept an unwanted request.

The application performs state-changing operations through GET requests without requiring consistent CSRF token validation. Because the form_checksum integrity check is conditional, an omitted parameter can leave the request unverified. This is CWE-352: Cross-Site Request Forgery, where an application relies on a victim's authenticated browser to accept an unwanted request.

Potential impact

  • Checkout records could be voided without the user's intent.
  • Invoice counters could be regenerated, disrupting billing workflows.
  • Ledger state and financial reporting could become inaccurate.
  • Audit records could reflect unauthorized or confusing changes.
  • Checkout records could be voided without the user's intent.
  • Invoice counters could be regenerated, disrupting billing workflows.
  • Ledger state and financial reporting could become inaccurate.
  • Audit records could reflect unauthorized or confusing changes.

General mitigation guidance

Common defensive patterns include:

  • Require unpredictable, session-bound CSRF tokens for every state-changing request, and reject missing or invalid tokens.
  • Use non-GET methods for operations that modify application state.
  • Treat checksums and other integrity parameters as mandatory only when they are reliably validated; do not make security checks conditional on optional input.
  • Apply authorization checks to each operation and limit billing permissions to the users who need them.
  • Consider same-site cookie settings and origin checks as additional defenses, not replacements for CSRF tokens.

Common defensive patterns include:

  • Require unpredictable, session-bound CSRF tokens for every state-changing request, and reject missing or invalid tokens.
  • Use non-GET methods for operations that modify application state.
  • Treat checksums and other integrity parameters as mandatory only when they are reliably validated; do not make security checks conditional on optional input.
  • Apply authorization checks to each operation and limit billing permissions to the users who need them.
  • Consider same-site cookie settings and origin checks as additional defenses, not replacements for CSRF tokens.

How teams detect issues like this

Review routes and handlers for state changes reachable through GET requests, especially when CSRF checks are optional or conditional. Static analysis and code review can look for missing token validation on mutating operations and tests that accept requests with omitted security parameters. Policy checks can prohibit state-changing GET handlers and require CSRF validation in billing workflows.

Review routes and handlers for state changes reachable through GET requests, especially when CSRF checks are optional or conditional. Static analysis and code review can look for missing token validation on mutating operations and tests that accept requests with omitted security parameters. Policy checks can prohibit state-changing GET handlers and require CSRF validation in billing workflows.

Sources

SourceLink
github.comgithub.com/openemr/openemr/commit/f760adc7bddaf9d118e1a0d40590e686783ed21b
github.comgithub.com/openemr/openemr/pull/13197
github.comgithub.com/openemr/openemr/releases/tag/v8_3_0
github.comgithub.com/openemr/openemr/security/advisories/GHSA-p8j4-vmx9-rfhj

Frequently asked

questions

A cross-site request can be initiated from another site, but it relies on an authenticated billing user's browser being able to reach the affected OpenEMR interface.

The attacker generally needs the victim to be signed in with an account authorized to perform the affected checkout or invoice operations. The attacker does not necessarily need direct access to that account.

Require valid CSRF tokens for all state-changing operations, reject requests when tokens are missing, and avoid using GET for changes.

Enforce CSRF protections consistently in shared request-handling patterns, test that missing tokens are rejected, and review billing endpoints for state changes and appropriate authorization.

A cross-site request can be initiated from another site, but it relies on an authenticated billing user's browser being able to reach the affected OpenEMR interface.

The attacker generally needs the victim to be signed in with an account authorized to perform the affected checkout or invoice operations. The attacker does not necessarily need direct access to that account.

Require valid CSRF tokens for all state-changing operations, reject requests when tokens are missing, and avoid using GET for changes.

Enforce CSRF protections consistently in shared request-handling patterns, test that missing tokens are rejected, and review billing endpoints for state changes and appropriate authorization.

Find out what's already
exploitable in your codebase.