CVE-2026-71537 Overview
Paymenter is a free and open-source webshop solution for managing hosting services. CVE-2026-71537 is a race condition [CWE-362] in the service upgrade workflow that allows an authenticated customer to duplicate account credit balances by submitting concurrent downgrade requests. The flaw resides in app/Livewire/Services/Upgrade.php::doUpgrade(), which checks Service::upgradable for a pending upgrade and later calls $credit->increment('amount', abs($price)) without wrapping these operations in a database transaction or lockForUpdate(). Paymenter version 1.5.7 fixes the issue.
Critical Impact
An authenticated customer can trigger multiple simultaneous downgrade requests to inflate their account credit balance, producing spendable refunds that exceed the value of a single legitimate downgrade.
Affected Products
- Paymenter (open-source hosting webshop platform)
- All versions prior to 1.5.7
- Deployments exposing the customer service management interface
Discovery Timeline
- 2026-09-18 - CVE-2026-71537 published to NVD
- 2026-09-24 - Last updated in NVD database
Technical Details for CVE-2026-71537
Vulnerability Analysis
The vulnerability is a classic time-of-check to time-of-use (TOCTOU) race condition in Paymenter's service downgrade flow. When a customer initiates a downgrade, doUpgrade() first evaluates the Service::upgradable attribute to confirm no pending upgrade exists. It then creates a new upgrade record and increments the customer's account credit balance with the refund amount.
Because these steps execute outside of a database transaction and without row-level locking, concurrent HTTP requests can each pass the upgradable check before any of them writes a pending upgrade record. Each request then proceeds to create its own upgrade entry and add the refund to the same credit row. The result is a single downgrade producing multiple spendable refunds that a customer can use against future invoices.
Root Cause
The root cause is missing concurrency control on a state-mutating operation. The check-then-act pattern in doUpgrade() is not atomic. Neither DB::transaction nor lockForUpdate() spans the read of Service::upgradable and the subsequent $credit->increment('amount', abs($price)) write. Under concurrent load, multiple requests observe a stale "no pending upgrade" state and each performs the credit increment.
Attack Vector
Exploitation requires an authenticated customer account with an active downgradable service. The attacker sends multiple concurrent downgrade HTTP requests targeting the same service. Each parallel request bypasses the eligibility check and independently credits the customer's balance. No elevated privileges, user interaction, or network position beyond standard authenticated access is required. Refer to the GitHub Security Advisory GHSA-5gmm-hjfj-8ff7 for full technical details.
Detection Methods for CVE-2026-71537
Indicators of Compromise
- Multiple upgrade records created for the same service_id within a short time window (typically sub-second).
- Credit balance increments on a single customer account that exceed the value of a single legitimate downgrade.
- Bursts of concurrent POST requests from the same authenticated session targeting the downgrade endpoint.
Detection Strategies
- Query the upgrades table for duplicate rows sharing identical service_id, type, and near-identical created_at timestamps.
- Reconcile the credits table against the count of processed downgrade records per customer to identify balance inflation.
- Enable web server access logging and alert on repeated identical downgrade requests from one session within a narrow time window.
Monitoring Recommendations
- Instrument application logs around doUpgrade() invocations to capture request identifiers, session IDs, and timestamps.
- Monitor Laravel database query logs for credit increment operations lacking a surrounding transaction context.
- Track anomalous credit-to-invoice ratios per customer as a leading indicator of abuse.
How to Mitigate CVE-2026-71537
Immediate Actions Required
- Upgrade Paymenter to version 1.5.7 immediately using the GitHub Release v1.5.7.
- Audit the upgrades and credits tables for evidence of duplicate refund records prior to patching.
- Reverse any inflated credit balances identified during the audit and notify affected billing workflows.
Patch Information
The fix is committed in Paymenter version 1.5.7. The upstream patch introduces proper transactional boundaries and locking around the upgrade check and credit increment. Review the GitHub Commit for the exact code changes applied to app/Livewire/Services/Upgrade.php.
Workarounds
- Rate-limit the downgrade endpoint at the reverse proxy or web application firewall to one request per session per second.
- Temporarily disable customer self-service downgrades and process them manually through administrative review until the patch is applied.
- Add a unique database constraint on pending upgrade records per service to prevent duplicate row creation.
# Configuration example: upgrade Paymenter to the patched release
git fetch --tags
git checkout v1.5.7
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.