highCVSS 7.4Vulnerability

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)

[Software]rubygems/pay

HAS_WEAKNESS (1)

[Weakness]Observable Timing Discrepancy

REPORTED_BY (1)

[Source]GitHub Advisory Database

VULNERABLE_TO (1)

[Software]rubygems/pay

Explore deeper with Ninja Signal's threat intelligence graph

GHSA-mjgf-xj26-9qf9 (CVSS 7.4) — Ninja Signal Threat Intelligence | Ninja Signal