CVE-2026-59805 Overview
CVE-2026-59805 is a broken access control vulnerability in Gumroad versions before 2026.07.06.2. The flaw resides in the PurchasesController, where the revoke_access and undo_revoke_access actions lack seller ownership validation. Authenticated sellers can send crafted PUT requests to manipulate the is_access_revoked status on purchases belonging to other sellers' products. This allows attackers to revoke or restore buyer access to digital goods they do not own. The issue is tracked as CWE-862: Missing Authorization and is classified as an Insecure Direct Object Reference (IDOR).
Critical Impact
Any authenticated seller can tamper with purchase access records across the entire Gumroad platform, disrupting legitimate buyer entitlements for products owned by other sellers.
Affected Products
- Gumroad versions prior to 2026.07.06.2
- The PurchasesController component (app/controllers/purchases_controller.rb)
- Self-hosted deployments of the antiwork/gumroad codebase
Discovery Timeline
- 2026-07-08 - CVE-2026-59805 published to NVD
- 2026-07-08 - Last updated in NVD database
- v2026.07.06.2 - Fixed release published on GitHub Releases
Technical Details for CVE-2026-59805
Vulnerability Analysis
The PurchasesController exposes several actions that require the authenticated user to be the seller associated with a given purchase. The controller enforces this ownership check through a before_action filter named verify_current_seller_is_seller_for_purchase. Before the patch, this filter was applied only to update, change_can_contact, and cancel_preorder_by_seller. The revoke_access and undo_revoke_access actions were omitted from the filter list, so the controller did not verify that the currently authenticated seller owned the product tied to the target purchase.
An authenticated seller can submit a PUT request referencing an arbitrary purchase identifier. The controller then flips the is_access_revoked boolean on that purchase without checking ownership. The consequence is unauthorized modification of buyer entitlement state across every seller on the platform.
Root Cause
The root cause is a missing authorization check [CWE-862] on server-side state-changing actions. The controller trusted the object identifier supplied in the request without confirming that the current seller was authorized to act on it. This is a textbook Insecure Direct Object Reference pattern.
Attack Vector
Exploitation requires an authenticated Gumroad seller account. The attacker enumerates or obtains purchase IDs belonging to other sellers and issues PUT requests to the revoke_access and undo_revoke_access endpoints. No user interaction from the victim is required, and the attack is delivered over the network against the application's HTTP endpoints.
update resend_receipt change_can_contact cancel_preorder_by_seller receipt
revoke_access undo_revoke_access confirm_receipt_email
]
- before_action :verify_current_seller_is_seller_for_purchase, only: %i[update change_can_contact cancel_preorder_by_seller]
+ before_action :verify_current_seller_is_seller_for_purchase, only: %i[update change_can_contact cancel_preorder_by_seller revoke_access undo_revoke_access]
before_action :hide_layouts, only: %i[subscribe unsubscribe receipt confirm_receipt_email]
before_action :set_noindex_header, only: [:receipt, :confirm_receipt_email]
Source: GitHub commit e7fd0e6. The patch extends the verify_current_seller_is_seller_for_purchase filter to include the two vulnerable actions, restoring ownership validation before state changes are permitted.
Detection Methods for CVE-2026-59805
Indicators of Compromise
- Application logs showing PUT requests to revoke_access or undo_revoke_access endpoints originating from a seller account that does not own the referenced purchase
- Unexplained changes to the is_access_revoked column on purchases records across multiple sellers
- Buyer support tickets reporting sudden loss or restoration of access to previously purchased products
- Access log spikes containing sequential or enumerated purchase identifiers under a single authenticated session
Detection Strategies
- Correlate the seller ID in each authenticated session against the product owner of any purchase modified by revoke_access or undo_revoke_access requests
- Alert on any request where the acting seller ID does not match the seller ID linked to the purchase record
- Review database audit trails for is_access_revoked toggles that lack a corresponding legitimate business event
Monitoring Recommendations
- Enable request-level logging on the PurchasesController with full user, purchase, and product identifiers
- Track rate of revoke_access and undo_revoke_access calls per seller and flag statistical outliers
- Monitor for anomalous cross-seller reference patterns in web application firewall telemetry
How to Mitigate CVE-2026-59805
Immediate Actions Required
- Upgrade Gumroad to release v2026.07.06.2 or later, which includes the fix from pull request #5731
- Audit the purchases table for unauthorized is_access_revoked changes made prior to patching and reconcile with legitimate seller activity
- Rotate session tokens for any seller account suspected of exploiting the flaw and review its recent request history
Patch Information
The fix is committed in commit e7fd0e6 and released in v2026.07.06.2. Additional context is available in issue #5725 and the VulnCheck advisory.
Workarounds
- Apply the upstream before_action change to add revoke_access and undo_revoke_access to the verify_current_seller_is_seller_for_purchase filter if immediate upgrade is not possible
- Temporarily disable the revoke_access and undo_revoke_access routes at the reverse proxy or load balancer until the patched release is deployed
- Restrict seller account creation and require manual review for new sellers until remediation is complete
# Verify the deployed Gumroad version matches the patched release
git -C /path/to/gumroad describe --tags
# Expected output: v2026.07.06.2 (or later)
# Confirm the patched before_action is present in the controller
grep -n "verify_current_seller_is_seller_for_purchase" \
app/controllers/purchases_controller.rb
# Expected: the filter list includes revoke_access and undo_revoke_access
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

