CVE-2026-55219 Overview
CVE-2026-55219 is a race condition vulnerability in Paymenter, an open-source webshop solution for hosting service management. The flaw exists in the credit payment implementation within app/Livewire/Invoices/Show.php in versions prior to 1.5.5. The code invokes a pessimistic row lock using lockForUpdate() without wrapping it in an active database transaction. MySQL and MariaDB silently ignore row-level locks when no enclosing transaction exists. Concurrent payment requests can therefore read the same credit balance simultaneously and approve multiple invoice payments against a single balance. The issue is tracked under [CWE-362] and is fixed in version 1.5.5.
Critical Impact
Authenticated attackers can exploit this concurrency flaw to pay multiple invoices using the same credit balance, causing direct financial and resource loss to the platform.
Affected Products
- Paymenter versions prior to 1.5.5
- Deployments backed by MySQL or MariaDB databases
- Any Paymenter instance exposing the credit payment flow to authenticated users
Discovery Timeline
- 2026-07-20 - CVE-2026-55219 published to NVD
- 2026-07-23 - Last updated in NVD database
Technical Details for CVE-2026-55219
Vulnerability Analysis
The vulnerability is a time-of-check to time-of-use (TOCTOU) race condition in Paymenter's credit payment handler. The Livewire component in app/Livewire/Invoices/Show.php reads the user's credit balance, verifies it covers the invoice, then debits the balance and calls ExtensionHelper::addPayment() to provision the purchased services. The code attempts to serialize concurrent access with Laravel's lockForUpdate() helper. That helper only emits a SELECT ... FOR UPDATE clause, which MySQL and MariaDB honor solely within an active transaction. Because no DB::transaction() or beginTransaction() wraps the query, the database drops the lock request silently and services the reads concurrently.
Root Cause
The root cause is misuse of pessimistic locking outside a transactional context. lockForUpdate() is a query modifier, not a standalone synchronization primitive. Without START TRANSACTION, the storage engine has no scope in which to hold row locks until commit. The developer intent was to serialize the check-and-decrement of the credit balance, but the runtime behavior degrades to an unlocked read followed by an unlocked update.
Attack Vector
An authenticated user with a positive credit balance sends two or more parallel HTTP requests to pay different invoices within the same millisecond window. Each request reads the original balance, evaluates it as sufficient, and processes the payment through ExtensionHelper::addPayment(). Every request marks its invoice as paid and triggers service provisioning, even though only one payment's worth of credit existed. The attack requires only standard user privileges and a scriptable HTTP client capable of dispatching concurrent requests.
No verified exploit code is publicly available. See the GitHub Security Advisory for the vendor's technical description of the fix.
Detection Methods for CVE-2026-55219
Indicators of Compromise
- Multiple invoices marked paid with identical or near-identical timestamps for the same user account
- Credit balance ledger entries showing a single debit paired with multiple addPayment provisioning events
- Unexpected service provisioning volume without corresponding gateway transactions or ledger deductions
Detection Strategies
- Audit the invoices and credit ledger tables for cases where a user's cumulative paid invoice totals exceed their debited credit within short time windows
- Correlate application logs from ExtensionHelper::addPayment() against database write timestamps to identify sub-second bursts against a single user
- Add web server log analytics that flag concurrent POST requests to the credit payment endpoint from the same session
Monitoring Recommendations
- Instrument the credit payment handler with structured logging that records pre- and post-balance for every request
- Alert when the same authenticated user submits more than one payment request to the credit endpoint within a 500 ms window
- Reconcile provisioned services against successful payment events on a scheduled cadence to surface silent over-provisioning
How to Mitigate CVE-2026-55219
Immediate Actions Required
- Upgrade Paymenter to version 1.5.5 or later, which wraps the credit payment logic in a proper database transaction
- Temporarily disable the credit balance payment method until the upgrade is deployed if patching is delayed
- Review historical payment records for evidence of duplicate provisioning tied to a single credit debit and reconcile balances
Patch Information
The maintainers fixed the vulnerability in Paymenter 1.5.5 by enforcing an explicit database transaction around the lockForUpdate() query, allowing MySQL and MariaDB to hold the row lock through the balance check and decrement. Full technical details are available in the GitHub Security Advisory GHSA-pgcq-8grm-5rx9.
Workarounds
- Restrict access to the credit payment endpoint through application-layer rate limiting that rejects concurrent requests per session
- Introduce a reverse proxy rule enforcing single-flight semantics on POST requests to invoice payment routes
- Manually reconcile credit balances daily and freeze accounts exhibiting mismatched debit-to-payment ratios until the upgrade is applied
# Upgrade Paymenter to the patched release
cd /path/to/paymenter
git fetch --tags
git checkout v1.5.5
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

