GHSA-mjgf-xj26-9qf9
## Summary `Pay::Webhooks::PaddleBillingController#valid_signature?` (`app/controllers/pay/webhooks/paddle_billing_controller.rb`) verifies the Paddle Billing webhook signature by computing `OpenSSL::HMAC.hexdigest(...)` and comparing it to the attacker-supplied header value using Ruby's `String#==`. Ruby's `==` is non-constant-time — it returns as soon as the first byte mismatches — and exposes a per-byte timing side channel on the webhook signature verification path. The canonical mitigation is to use a constant-time primitive (`OpenSSL.fixed_length_secure_compare` / `ActiveSupport::SecurityUtils.secure_compare`). ## Impact - **CWE-208** — Observable Timing Discrepancy on the webhook signature verifier. - An attacker who can deliver requests to the `/pay/webhooks/paddle_billing` mount point can probe the verifier with guessed `Paddle-Signature` header values. Because `String#==` short-circuits on the first mismatching byte, the response-time distribution shifts as the prefix of the guess matches the real hex digest. - A signature recovered through the oracle lets the attacker deliver forged Paddle Billing webhook events (e.g. `subscription.created` / `transaction.completed`) against the host application. Pay's webhook processor enqueues a `Pay::Webhooks::ProcessJob` for any accepted webhook, which downstream applications use to update billing state — including provisioning paid features, recording refunds, and triggering customer notifications. - The endpoint is internet-reachable by definition (Paddle must POST events to it). ## Affected versions `pay` (rubygem) ≤ v11.6.1 (latest release as of 2026-05-27). ## Vulnerable code (file:line) `app/controllers/pay/webhooks/paddle_billing_controller.rb`: ```ruby 24: def valid_signature?(paddle_signature) 25: return false if paddle_signature.blank? 26: 27: ts_part, h1_part = paddle_signature.split(";") 28: _, ts = ts_part.split("=") 29: _, h1 = h1_part.split("=") 30: 31: sig
Properties
- ghsa_id
- GHSA-mjgf-xj26-9qf9
- summary
- pay-rails/pay: non-constant-time HMAC comparison in Paddle Billing webhook signature verifier
- severity
- high
- cvss_score
- 7.4
- cve_id
- GHSA-mjgf-xj26-9qf9
- cvss_vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- is_ghsa_only
- true
- ghsa_published
- 2026-07-01T18:57:02Z
- source_url
- https://github.com/advisories/GHSA-mjgf-xj26-9qf9
- ghsa_updated
- 2026-07-01T18:57:03Z
Related Entities (4)
AFFECTS (1)
HAS_WEAKNESS (1)
REPORTED_BY (1)
VULNERABLE_TO (1)
Explore deeper with Ninja Signal's threat intelligence graph