GHSA-mjgf-xj26-9qf9HIGHCVSS 7.4

pay-rails/pay: non-constant-time HMAC comparison in Paddle Billing webhook signature verifier

Published Jul 1, 2026·Updated Jul 1, 2026

Description

## 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: signed_payload = "#{ts}:#{request.raw_post}" 32: 33: key = Pay::PaddleBilling.signing_secret 34: data = signed_payload 35: digest = OpenSSL::Digest.new("sha256") 36: 37: hmac = OpenSSL::HMAC.hexdigest(digest, key, data) 38: hmac == h1 # <-- non-constant-time '==' 39: end ``` `hmac` is the 64-character hex-encoded SHA-256 HMAC of `"<ts>:<raw_post>"` under the application's configured Paddle Billing signing secret. The comparison with `h1` (the attacker-supplied `h1=` token from the `Paddle-Signature` header) uses Ruby's native `String#==`, which is implemented in MRI as `rb_str_equal` and returns immediately on the first byte mismatch. ## How an attacker reaches this code 1. Any Pay-using Rails application mounting `Pay::Engine` exposes `POST /pay/webhooks/paddle_billing` to the public internet (Paddle requires the endpoint to be reachable). The controller is configured by default in `config/routes.rb` when `paddle_billing` is enabled. 2. The controller's `before_action :verify_signature` invokes `valid_signature?` on every inbound request. 3. An attacker repeatedly POSTs forged webhook payloads with `Paddle-Signature: ts=<now>;h1=<guess>` headers and measures the response time. The verifier returns early on the first mismatching byte of the hex digest; with a sufficient probe count per byte position, response-time distribution reveals when the prefix of `<guess>` matches the real `hmac`. 4. A signature recovered through the oracle lets the attacker forge arbitrary Paddle Billing webhook deliveries. ## Proof of concept (microbenchmark) Local Ruby microbenchmark isolating the verifier comparison path: ```ruby require 'openssl' require 'benchmark' require 'securerandom' key = SecureRandom.hex(32) payload = '1730000000:{"event_type":"transaction.completed"}' real_hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, payload) puts "real_hmac=#{real_hmac}" def verify(real, guess) real == guess # mirrors paddle_billing_controller.rb:38 end guesses = { 'all-wrong' => ('0' * real_hmac.length), 'match-1byte' => real_hmac[0..0] + '0' * (real_hmac.length - 1), 'match-32byte' => real_hmac[0..31] + '0' * (real_hmac.length - 32), 'match-63byte' => real_hmac[0..62] + '0', 'exact-match' => real_hmac.dup, } iters = 10_000_000 3.times { guesses.each_value { |g| 1_000_000.times { real_hmac == g } } } # warmup guesses.each do |label, g| t = Benchmark.realtime { iters.times { real_hmac == g } } puts "#{label.ljust(15)} avg_ns=#{(t * 1e9 / iters).round}" end ``` This isolates the same `String#==` path used by `valid_signature?`. The static defect is verifiable by `bundle show pay` and reading line 38 of the controller. ## End-to-end reproduction against `gem install pay --version 11.6.1` Minimal Rails 8 app mounting `Pay::Engine` with `paddle_billing` enabled: ```bash gem install rails -v 8.0.2 rails new payapp --skip-test --skip-bundle cd payapp echo "gem 'pay', '11.6.1'" >> Gemfile echo "gem 'paddle', '~> 2.0'" >> Gemfile bundle install bin/rails g pay:install # config/initializers/pay.rb adds Pay.setup, paddle_billing config # config/routes.rb already has 'mount Pay::Engine => "/pay"' from generator bin/rails server & # attacker probes the webhook endpoint WEBHOOK="http://127.0.0.1:3000/pay/webhooks/paddle_billing" BODY='{"event_type":"transaction.completed","data":{}}' TS=$(date +%s) # Try guesses with different prefix-match counts; response-time delta is the oracle for guess in 0000000000000000000000000000000000000000000000000000000000000000 \ a000000000000000000000000000000000000000000000000000000000000000 ; do for _ in 1 2 3; do curl -s -w '%{time_total}\n' -o /dev/null \ -X POST -H "Paddle-Signature: ts=$TS;h1=$guess" \ -H 'Content-Type: application/json' -d "$BODY" "$WEBHOOK" done done ``` The static defect is verifiable by: ``` $ bundle show pay .../gems/pay-11.6.1 $ sed -n '38p' .../gems/pay-11.6.1/app/controllers/pay/webhooks/paddle_billing_controller.rb hmac == h1 ``` After the fix is applied, the verifier uses `ActiveSupport::SecurityUtils.secure_compare`, which compares all bytes regardless of mismatch position, and the timing oracle closes. ## Suggested fix Replace `==` with `ActiveSupport::SecurityUtils.secure_compare` (Pay is a Rails engine, so ActiveSupport is always available). ```diff def valid_signature?(paddle_signature) return false if paddle_signature.blank? ts_part, h1_part = paddle_signature.split(";") _, ts = ts_part.split("=") _, h1 = h1_part.split("=") signed_payload = "#{ts}:#{request.raw_post}" key = Pay::PaddleBilling.signing_secret data = signed_payload digest = OpenSSL::Digest.new("sha256") hmac = OpenSSL::HMAC.hexdigest(digest, key, data) - hmac == h1 + return false if h1.nil? || hmac.bytesize != h1.bytesize + ActiveSupport::SecurityUtils.secure_compare(hmac, h1) end ``` The bytesize-equality guard ensures `secure_compare` does not return early on a length mismatch (it falls back to `==` if lengths differ on older Rails versions). For the Paddle Billing signing format the hex tag is a fixed 64 chars. ## Credit Reported by tonghuaroot (https://github.com/tonghuaroot).

Affected Packages (1)

payGEM
Fixed in = 11.6.1

Public Exploits & PoCs100 found

PoC: CVE-2026-6307

Google Chrome CVE-2026-6307 PoC

3

PoC: root-sonim-xp3800

app that ports CVE-2019-2215 to arm32 and mounts a su binary to /sbin with denylist + root app installer. firehose/Magisk guide included

2

PoC: CVE-2026-34835-Black-box-Analysis

A black-box (DAST) security analysis of CVE-2026-34835 focusing on external validation methodology, observable behavior, security impact, and defensive recommendations.

1

PoC: Linux-Kernel-Vulnerabilities-CVE-2026-23111

High Severity LPE vulnerability in Linux Kernel, with a CVS score of 7.8. An inverted check from user enables a process inside the container to break out of the sandbox along with full root privileges on user PC. I have been investigating about this vulnerability and has a lightweight script that runs in the terminal to check if you are vulnerable.

1

PoC: xperia_5_bl_unlocker_poc

My take on unlocking Xperia 5 SO-01M for p42 bootloader using CVE-2021-1931

1

PoC: cve-2026-23111-poc

scuffed PoC for CVE-2026-23111. Made and ran on Linux Kernel 6.12.69

1

PoC: CVE_ADC_IOC_2026

Citrix NetScaler CVE Preconditions Checker as per CTX696604 | Supported CVE : CVE-2026-8451, CVE-2026-8452, CVE-2026-8655, CVE-2026-10816, CVE-2026-10817, and CVE-2026-13474

1

PoC: CVE-2026-46300

CVE-2026-43284 - CVE-2026-43500 - CVE-2026-46300 Variant of dirtyfrag exploit

1

PoC: CVE-2025-69212-PoC

OpenSTAManager v2.9.8 and earlier versions contain a critical OS Command Injection vulnerability in the P7M (signed XML) file decoding function.

1

PoC: CVE-2026-24418

OpenSTAManager v2.9.8 and earlier contain a critical Error-Based SQL Injection vulnerability in the bulk operations handler for the Scadenzario (Payment Schedule) module.

1

PoC: CVE-2026-69212

Python poc, exploit for CVE-2025-69212

1

PoC: CVE-2026-49468-LiteLLM-Auth-Bypass

CVE-2026-49468 — LiteLLM (<1.84.0) unauthenticated auth bypass via Host-header route confusion. PoC + docker lab.

PoC: CVE-2026-28995

# CVE-2026-28995 Proof of Concept for CVE-2026-28995 — Path Traversal vulnerability in App Intents on iOS 26.4.2 and below.

PoC: Advanced-CVE-2026-53753

Crawl4AI is an open-source LLM friendly web crawler & scraper. Prior to 0.8.7, the _safe_eval_expression() function in the computed fields feature uses an AST validator that only blocks attributes starting with underscore.

PoC: opensource_defect_repare_cc

Redis 7.0.0 核心模块重构与漏洞修复交付(重构 sds/adlist/intset/listpack,相似度≤20%;修复 CVE-2023-25155/28856、CVE-2024-31449、CVE-2022-36021、CVE-2022-31144 等漏洞)

PoC: opensource_defect_repair_cc

Redis 7.0.0 核心模块重构与漏洞修复交付(重构 sds/adlist/intset/listpack,相似度≤20%;修复 CVE-2023-25155/28856、CVE-2024-31449、CVE-2022-36021、CVE-2022-31144 等漏洞)

PoC: CVE-2026-56782

Gorse < 0.5.10 contains an authentication bypass caused by empty admin_api_key in /api/dump and /api/restore endpoints, letting unauthenticated remote attackers access and modify protected data, exploit requires default empty admin_api_key configuration.

PoC: CVE-2026-54477

CVE-2026-54477: Admin Panel Missing Security Headers (clickjacking/XSS) - Gardyn (ICSA-26-183-03)

PoC: CVE-2026-55726

CVE-2026-55726: Publicly Listable Azure Blob Storage Container (device logs) - Gardyn (ICSA-26-183-03)

PoC: CVE-2026-52217-VTEX-Checkout-CrossTenant-IDOR

The VTEX Checkout Service exposes OrderForm data through the endpoints `/api/checkout/pub/orderForm/{orderFormId}` and `/attachments/*`. These endpoints do not validate the tenant (store account) of the authenticated session against the ownership of the requested OrderForm.

PoC: CVE-2026-13768

CVE-2026-13768: Privileged iothubowner IoT Hub credential — fleet enumeration, device RCE, home-network pivot — Gardyn (ICSA-26-183-03)

PoC: Code-27-Companion-Hub-Exploits

Proof of concept for CVE-2026-36027 and CVE-2026-36028

PoC: CVE-2026-38751-OpenSTAManager-Arbitrary-File-Upload-PoC

This repository contains a proof-of-concept (PoC) exploit for CVE-2026-38751, affecting OpenSTAManager ≤ 2.10. The vulnerability allows an authenticated attacker to upload a malicious module via the module update functionality, leading to arbitrary file upload and remote code execution (RCE).

PoC: CVE-2025-57819

CVE-2025-57819 - FreePBX Unauthenticated Remote Code Execution (RCE)

PoC: CVE-2026-48558

SimpleHelp OIDC Authentication Bypass PoC

PoC: Vulnerability-scanner

DESIGN AND IMPLEMENTATION OF A VULNERABILITY SCANNER FOR CVE-2026-45498 IN MICROSOFT DEFENDER

PoC: CVE-2026-33017

Python POC, Exploit for CVE-2026-33017

PoC: CVE-2021-27877-PoC

A modified version of the Rapid7 Metasploit module for CVE-2021-27877 that supports direct command execution for reliable vulnerability validation. Includes documentation explaining the exploit workflow, the module modifications, and usage examples.

PoC: CVE-2026-30784-rustdesk-poc

CVE-2026-30784: RustDesk hbbs Traffic Amplification PoC & PCAP Analysis

PoC: CVE-2026-52813

Gogs has Path Traversal in organization name that results in RCE through Git hooks

PoC: CVE-2026-53753

Crawl4AI <= 0.8.6 pre-auth RCE via AST sandbox escape (gi_frame.f_back.f_builtins chain) — CVSS 10.0

PoC: CVE-2025-69212

CVE-2025-69212 Proof-of-concept.

PoC: OpenSTAManager_RCE_Exploit-CVE-2026-38751-

OpenSTAManager RCE Exploit (CVE-2026-38751)

PoC: CVE-2025-69212-PoC

CVE-2025-69212 - OpenSTAManager OS Command Injection PoC

PoC: F5-BIG-IP

O F5 BIG-IP é uma plataforma de entrega e segurança de aplicações amplamente utilizada em ambientes corporativos. A CVE-2020-5902 é uma vulnerabilidade crítica no TMUI que, em versões não corrigidas, pode permitir acesso não autorizado e execução remota de código, reforçando a necessidade de atualização e gestão contínua de vulnerabilidades.

PoC: CVE-2026-6307-Longinus

CVE-2026-6307 PoC: Longinus - 2 Boundaries in One Bug https://nebusec.ai/research/v8-cve-2026-6307-writeup/)

PoC: CVE-2026-48907

CVE-2026-48907 PoC

PoC: CVE-2026-43735

Safari 跨域信息读取

PoC: cve-2025-24054-lab

Blue-team lab: detecting & mitigating CVE-2025-24054 (Windows NTLM hash disclosure) with Sysmon, Wazuh SIEM, and Group Policy

PoC: CVE-2026-42945

A flaw was found in NGINX, specifically within the ngx_http_rewrite_module. An unauthenticated attacker can exploit this vulnerability by sending crafted HTTP requests under specific rewrite configurations. This can lead to a heap buffer overflow in the NGINX worker process, which may result in arbitrary code execution

PoC: CVE-2026-51947-Advisory

Pivotal CRM's patch for an initial deserialization vulnerability was incomplete. The fix switched from BinaryFormatter to JSON.NET but left TypeNameHandling set to 4 without implementing SerializationBinder, allowing attackers to execute arbitrary code through malicious $type payloads. Fixed in 6.6.5.10 and Patch_CWE502_20260316.zip

PoC: CVE-2026-46331

pedit COW

PoC: Incident-Response-Report-TeamCity-Compromise-CVE-2024-27198-

CyberDefenders JetBrains Lab

PoC: CVE-2026-55488

motionEye's Absolute Path Traversal in Media File Handlers Allows Arbitrary File Read

PoC: CVE-2026-58138-Conductor-Unauth-RCE

CVE-2026-58138 — Conductor (3.21.21..<3.30.2) unauthenticated RCE via INLINE GraalVM evaluator (HostAccess.ALL). Lab + PoC, verified e2e (root).

PoC: CVE-2026-46490-samlify-SAML-Attribute-Injection

CVE-2026-46490 — samlify <2.13.0 SAML AttributeValue XML injection -> signed-assertion privilege escalation. Self-contained PoC, verified e2e.

PoC: CVE-2025-40271

CVE-2025-40271 Modifed By MadEploits

PoC: cve-2026-46331-pedit-cow-auditd-detection

Defensive validation of CVE-2026-46331 / pedit COW with auditd, AppArmor, mitigation comparison and detection logic.

PoC: cve-2015-1187-dir820l-reproduction

Independent reverse engineering and reproduction of CVE-2015-1187, an unauthenticated command injection in the D-Link DIR-820L (Rev A, v1.05B03). MIPS firmware extraction with binwalk, static analysis in Ghidra, and tracing the `ping_addr` parameter to its command-execution sink.

PoC: CVE-2012-1823

CVE-2012-1823 - PHP CGI Argument Injection Remote Code Execution (RCE)

PoC: CVE-2026-22557-Path-Traversal-Ubiquti-UniFi

CVE-2026-22557 Path Traversal Ubiquti UniFi Network Application

PoC: CVE-2026-48907

POC for CVE-2026-48907

PoC: CVE-2026-49869

Kestra Auth-Bypass Vulnerability Checker

PoC: CVE-2026-31694-POC

Linux kernel FUSE readdir cache out-of-bounds write (CVE-2026-31694): a malicious FUSE server overflows a page-cache page by 24 bytes. PoC plus an unprivileged local-root exploit via /etc/passwd page-cache corruption. Run only inside a VM.

PoC: IS

Ovaj sto se skida isto ovaj s metasplotiom kucas msf console pa onda search CVE-2017-7494 pa use exploit/linux/samba/is_known_pipeline pa show options pa set RHOSTS (ip servera) set RPORt 445 (port za tu ranjivist) SET payload linux/x86/meterpreter/reverse_tcp SET LHOST ip kalija SET LORT 4444 pa exploit i ako je ranjiv dobijemo sesiju

PoC: CVE-2026-46331

Chequeo y Fix de la vulnerabilidad "pedit COW"

PoC: CVE-2025-45422---Bbox

CVE-2025-45422: Proximus b-box UPnP Persistence & Access Control Bypass

PoC: CVE-2026-10580

PoC exploit for CVE-2026-10580 - Authentication Bypass in Hippoo Mobile App for WooCommerce <= 1.9.4 leading to Admin Account Takeover

PoC: CVE-2026-56121-Feast-Unauth-RCE

CVE-2026-56121 — Feast <0.63.0 unauthenticated RCE via gRPC registry dill.loads of OnDemandFeatureView UDF (pre-auth). Lab + PoC, verified e2e.

PoC: CVE-2026-46817

CVE-2026-46817 - Draft

PoC: CVE-2026-8037

CVE-2026-8037 - Draft

PoC: CVE-2026-27626-PoC

OliveTin is a self-hosted web UI for exposing predefined shell commands to end users. This repository contains a proof-of-concept demonstrating two independent OS command injection vectors in OliveTin's Shell mode execution path, both of which bypass the application's intended shell-argument safety checks.

PoC: cve-2024-31317

Detailed discussion of Zygote vulnerability CVE-2024-31317

PoC: CVE-2026-43700

https://support.apple.com/en-us/127685#:~:text=2026%2D43704%3A%20dr3dd-,WebKit,-Available%20for%3A%20macOS

PoC: CVE-2026-44789-n8n-PrototypePollution-RCE

CVE-2026-44789 — n8n <1.123.43 HTTP Request pagination prototype pollution to RCE (NODE_OPTIONS runner-spawn gadget). Lab + automated PoC, verified e2e.

PoC: CVE-2023-43364-Searchor-RCE-Exploit

POC exploit via unsafe `eval()` usage in Searchor (≤ 2.4.2)

PoC: CVE-2026-46817

CVE-2026-46817

PoC: cve-2026-46331-audit

cve-2026-46331-audit script

PoC: CVE-2026-56782-Gorse-Auth-Bypass

CVE-2026-56782 — Gorse <0.5.10 unauthenticated DB dump/restore (admin_api_key fail-open). Lab + PoC, verified e2e.

PoC: cve-2026-0000-reference

NIST CVE-2026-0000 Keylogger Analysis

PoC: CVE-2026-48907

CVE-2026-48907 – Joomla JCE Unauthenticated Remote Code Execution (RCE)

PoC: CVE-2026-53753-Crawl4AI-RCE

CVE-2026-53753 — Crawl4AI <0.8.7 unauthenticated RCE (AST sandbox escape via gi_frame.f_back). Lab + PoC, verified e2e.

PoC: cve-2023-4911-exploit-optimized

Pure C exploit for CVE-2023-4911 (Looney Tunables). No Python required. Features multi-processing brute-forcing, dynamic calibration, and integrated ELF parser.

PoC: CVE_2024_1086_vulnerability_check

CVE-2024-1086 vulnerability

PoC: CVE-2026-43503

DirtyClone - local privilege escalation (LPE) proof-of-concept targeting a kernel/XFRM-related vulnerability described in the source as CVE-2026-43503

PoC: cve-2026-9082-drupal

drupal-postgresql-rce

PoC: graylog-cve-2024-24824-exploit

Proof-of-concept exploit for CVE-2024-24824 demonstrating how an arbitrary class loading primitive can be transformed into remote code execution on vulnerable Graylog deployments.

PoC: CVE-2026-55200

CVE-2026-55200 - Critical libssh2 Remote Code Execution Vulnerability

PoC: By-Poloss..-..CVE-2026-48939

iCagenda Unauthenticated File Upload to RCE

PoC: cve-2025-0133

CVE-2025-0133 Scanner | Palo Alto GlobalProtect XSS Checker

PoC: CVE-2026-22226

Proof of Concept for the CVE-2026-22226

PoC: CVE-2026-20253

POC for CVE-2026-20253

PoC: Joomla_CVE_2026_48907

cve-2026-48907 scanner

PoC: DirtyClone

Python Proof of Concept for DirtyClone (CVE-2026-43503) - Linux kernel LPE via page-cache corruption

PoC: WiseDelete

Windows utility that demonstrates user-mode interaction with the vulnerable WiseDelfile64.sys driver and uses CVE-2025-66680 to perform kernel-assisted file deletion.

PoC: CVE-2025-55182-React2Shell-RCE

React2Shell (CVE-2025-55182) PoC

PoC: CVE-2026-48908

Unauthenticated RCE PoC for CVE-2026-48908 SP Page Builder (Joomla) arbitrary file upload and remote code execution exploit with mass scaning support.

PoC: WiseDelete

A lightweight Windows utility demonstrating user-mode interaction with the vulnerable WiseDelfile64.sys driver using CVE-2025-66680 to perform kernel-assisted file deletion.

PoC: CVE-2026-23918-Double-free-Apache-httpd-mod_http2

Double-free in Apache httpd mod_http2 stream cleanup leading to pre-auth RCE

PoC: CVE-2018-18778

CVE-2018-18778 - ACME mini_httpd Arbitrary File Read

PoC: CVE-2023-0386-OverlayFS

Copy fake in-memory files to disk using overlayFS

PoC: CVE-2026-49048-JoomCCK-SQLi

CVE-2026-49048 — JoomCCK 6.4.0 Unauthenticated SQL Injection (CVSS 9.8)

PoC: crypto-lab-merkle-proofs

Browser-based Merkle tree demo — build a tree, generate inclusion proofs, recompute the root hash by hash, and replay the RFC 6962 second-preimage and CVE-2012-2459 attacks. Real SHA-256. No backend.

PoC: react2shell-exploit

React2Shell: CVE-2025-55182

PoC: CVE-2026-12485

CVE-2026-12485

PoC: DevHub-HTB-Walkthrough

Hack The Box - DevHub Machine Walkthrough (Medium Linux, CVE-2026-23744, Chisel Tunneling, Jupyter, Root Privilege Escalation)

PoC: CVE-2026-41179

POC for CVE-2026-41179

PoC: dirtyclone-exploit

CVE-2026-46331 — Linux Kernel Local Privilege Escalation TC pedit + IPsec TEE Page Cache Corruption · Affected kernels: ≤ 6.12.9

PoC: CVE-2026-27654

Обзор n-day уязвимости на русском языке.

PoC: CVE-2026-41940-PoC

CVE-2026-41940 authentication bypass vulnerability proof-of-concept

CVSS Vector

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

References

View on NVD Search GitHub Search Google

Get alerted for CVEs like this

Register your stack and get notified within minutes when a matching CVE drops.

Start monitoring free