# CVE-2026-70658: Pay timing attack in Paddle Billing webhook signature validation

Source: https://junglewise.ai/threats/cve-2026-70658-pay-timing-attack-in-paddle-billing-webhook-signature-validation  
Publisher: Junglewise Threat Intelligence, https://junglewise.ai/threats  
Published: 2026-09-14. Updated: 2026-09-26  
License: CC BY 4.0 with a link back

CVE-2026-70658 · Severity: high · CVSS 7.4 · Published 2026-09-14

Pay is a payment processing engine for Ruby on Rails applications that handles billing integrations with providers like Paddle. Prior to version 11.6.2, a flaw in webhook signature verification allowed attackers to forge webhook messages through timing analysis, potentially enabling unauthorized billing changes, feature provisioning, refunds, or fake customer notifications without proper authorization.

Vendors: [RubyGems](https://junglewise.ai/threats/vendors/rubygems).

## Quick answers

**Is CVE-2026-70658 exploited in the wild?** No. Junglewise Threat Intelligence has no report of CVE-2026-70658 being exploited in the wild.

**How severe is CVE-2026-70658?** High severity, with a CVSS score of 7.4, published 14 September 2026.

**Which products and versions are affected?** pay (RubyGems) ECOSYSTEM:introduced=0,last_affected=11.6.1.

**Is there a fix for CVE-2026-70658?** A patch was published on 2026-07-06: Version 11.6.2 released with fix using ActiveSupport::SecurityUtils.secure_compare Junglewise finds every place you run it, drafts the upgrade and applies it once you approve.

**How is CVE-2026-70658 attacked?** It is attacked over the network.

**Am I affected by CVE-2026-70658?** Check whether you run pay (RubyGems) at an affected version. Junglewise does that check for you around the clock: connect your code, cloud and domains, and it matches new vulnerabilities like this one against what you actually run and tells you when one reaches you.

## Technical details

The vulnerability is a timing-based signature forgery attack (CWE-208, Timing Attack) in the PaddleBillingController#valid_signature? method. The code used Ruby's standard String#== operator to compare a computed 64-character SHA-256 HMAC digest with an attacker-controlled token from the Paddle-Signature header. Because String#== short-circuits on the first byte mismatch, an attacker can measure response timing across repeated requests to infer matching digest prefixes and eventually reconstruct a valid signature. The attack is unauthenticated and network-accessible at the /pay/webhooks/paddle_billing endpoint. Once a valid signature is forged, malicious webhooks are processed through Pay::Webhooks::ProcessJob with full authority to modify billing state. The fix, released in 11.6.2, replaces String#== with ActiveSupport::SecurityUtils.secure_compare, a constant-time comparison function, and adds a bytesize check for Rails compatibility.

## Affected products

- Pay Pay prior to 11.6.2

## Identifiers

- CVE-2026-70658
- GHSA-mjgf-xj26-9qf9

## Timeline

- 2026-09-14: disclosed
- 2026-07-06: patched: Version 11.6.2 released with fix using ActiveSupport::SecurityUtils.secure_compare

## References

- [https://github.com/pay-rails/pay/commit/ba6494109d88209fba2a4df2d9d6373fe81ed805](https://github.com/pay-rails/pay/commit/ba6494109d88209fba2a4df2d9d6373fe81ed805)
- [https://github.com/pay-rails/pay/releases/tag/v11.6.2](https://github.com/pay-rails/pay/releases/tag/v11.6.2)

## Related threats

- [Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS) in Pay](https://junglewise.ai/threats/cve-2023-30614-improper-neutralization-of-script-related-html-tags-in-a-web-page)
