← Back to Feed CACHED · 2026-07-29 22:46:56 · CACHE_KEY CVE-2026-15144
CVE-2026-15144 · CWE-307 · Disclosed 2026-07-29

@fastify/rate-limit before 11

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone handed out unlimited arcade tokens by wearing a different hat each visit

CVE-2026-15144 affects @fastify/rate-limit versions prior to 11.2.0. The plugin's default keyGenerator uses the verbatim string from request.ip as the rate-limit bucket key. This creates two bypass vectors: (1) IPv6 prefix rotation — a standard residential or cloud IPv6 allocation gives an attacker a /64 block containing 2^64 unique addresses, each minting a fresh rate-limit bucket; and (2) representation aliasing — the same IPv6 address can be expressed in compressed (::1), expanded (0000:0000:…:0001), mixed-case, or IPv4-mapped (::ffff:10.0.0.1) forms, each treated as a distinct key. The fix in 11.2.0 introduces a normalizeIP() function and a configurable ipv6Subnet option (default /64) that canonicalizes addresses before keying. All applications using @fastify/rate-limit <11.2.0 behind IPv6-capable proxies (Cloudflare, AWS ALB, GCP LB, Vercel, Fly.io, Render, Railway) are in scope.

The vendor's HIGH 7.3 rating overweights the theoretical ceiling. The CVSS vector itself (C:L/I:L/A:L) correctly rates every impact dimension as *Low* — the 7.3 is inflated by the ease-of-reach metrics (network-accessible, no auth, no interaction). In practice, this vulnerability weakens a defense-in-depth control rather than directly achieving compromise. An attacker who bypasses the rate limit still needs to chain it with brute-force, credential stuffing, or volumetric abuse against an endpoint that *also* lacks MFA, account lockout, or CAPTCHA. Most enterprise-grade deployments of Fastify behind WAFs or API gateways already enforce rate limits upstream of the application layer, further reducing real-world exposure. A MEDIUM reassessment better reflects the actual blast radius.

"Rate-limit bypass via IPv6 rotation weakens a defense layer but doesn't directly compromise anything"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Identify IPv6-exposed Fastify service

The attacker fingerprints a target API or web application running Fastify with @fastify/rate-limit protecting a security-sensitive endpoint (login, OTP, password reset). The attacker confirms IPv6 connectivity by resolving the target's AAAA record or observing X-Forwarded-For headers passed by the reverse proxy.
Conditions required:
  • Target application uses @fastify/rate-limit <11.2.0
  • Target accepts IPv6 connections or sits behind a dual-stack proxy
Where this breaks in practice:
  • Many enterprise API deployments are IPv4-only behind internal load balancers
  • Some WAFs and CDNs normalize or strip IPv6 before it reaches the Fastify app
STEP 02

Acquire routable IPv6 prefix

The attacker obtains a /64 or larger IPv6 prefix. Cloud VPS providers (Vultr, Hetzner, OVH) routinely assign /64 or /48 blocks. Residential ISPs also allocate /56 or /48 by default. Tools like freebind (github.com/blechschmidt/freebind) hook into socket calls via LD_PRELOAD and bind each outgoing connection to a random address within the prefix.
Conditions required:
  • Attacker controls a machine with a routed IPv6 prefix
  • Linux with AnyIP configured: ip -6 route add local <prefix> dev lo
Where this breaks in practice:
  • Requires a VPS or ISP that delegates a prefix — commodity but not zero-cost
  • freebind requires Linux; no native Windows/macOS equivalent
STEP 03

Rotate source IPs to evade per-IP rate limit

Using freebind or a custom script, the attacker sends each request from a unique IPv6 address within their prefix. Since @fastify/rate-limit keys on the verbatim request.ip string, every request creates a new bucket and is never throttled. Alternatively, the attacker can send the same IPv4-mapped IPv6 address in different textual representations (::ffff:10.0.0.1 vs 0:0:0:0:0:ffff:a00:1) to bypass the limit even without a large prefix.
Conditions required:
  • Step 2 completed
  • Application does not normalize IPs upstream of the rate limiter
Where this breaks in practice:
  • Upstream WAFs or API gateways (Cloudflare, AWS WAF, Akamai) often enforce their own rate limits before traffic reaches Fastify
  • CDNs that canonicalize the X-Forwarded-For header eliminate the representation-aliasing vector
Detection/coverage: Anomaly detection on login-attempt velocity from diverse IPv6 addresses within the same /64 would flag this pattern. Most SIEM correlation rules key on /64 or /48 prefix, not individual IPs.
STEP 04

Execute brute-force or credential-stuffing attack

With the rate limit effectively disabled, the attacker hammers the target endpoint — login, OTP validation, password reset token — at full speed. Success depends entirely on whether the application has *additional* brute-force defenses beyond the now-bypassed rate limiter: MFA, progressive account lockout, CAPTCHA challenges, or credential-breach monitoring.
Conditions required:
  • Rate limit successfully bypassed
  • Target endpoint lacks secondary brute-force defenses
Where this breaks in practice:
  • MFA blocks credential stuffing even if rate limit is bypassed
  • Account lockout policies (e.g., 5-strike lockout) are independent of rate limiting
  • CAPTCHA or proof-of-work challenges add per-request cost the attacker cannot avoid
Detection/coverage: Failed-login alerting, impossible-travel detection, and credential-stuffing feeds (e.g., Have I Been Pwned, SpyCloud) all operate independently of rate limiting.
STEP 05

Account compromise or service degradation

If the brute-force succeeds, the attacker gains access to the targeted user account(s). Alternatively, the attacker can use the bypass for volumetric API abuse, exhausting backend resources or inflating costs on metered APIs. The blast radius is account-level or tenant-level — not fleet-scale or domain-scale.
Conditions required:
  • Step 4 succeeds against an account without MFA or lockout
Where this breaks in practice:
  • Blast radius is limited to individual accounts, not infrastructure
  • No privilege escalation, lateral movement, or persistence is inherent to this vuln
Detection/coverage: Standard IAM alerting on unusual login patterns, session anomalies, or geographic impossible-travel.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo known exploitation. Not listed on CISA KEV. No campaign reports. The IPv6 rotation technique is well-documented generically (HackerOne report #1154003, HackTricks rate-limit-bypass page) but no targeted exploitation of this specific CVE has been observed.
Proof-of-ConceptNo CVE-specific PoC published. However, the attack is trivial to reproduce using freebind (Linux LD_PRELOAD tool for per-socket IPv6 rotation) plus curl or any HTTP client. The representation-aliasing vector requires only header manipulation. Researcher/reporter: mcollina (Matteo Collina, Fastify core maintainer).
EPSS ScoreNot yet scored — CVE was disclosed 2026-07-29 (yesterday). FIRST EPSS data typically populates within 7–14 days of NVD publication.
KEV StatusNot listed. No CISA KEV entry as of 2026-07-30.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L7.3 HIGH. All three CIA impacts are *Low*. The score is driven entirely by the attack-reach metrics (Network, Low complexity, No privileges, No interaction). The unchanged scope is correct — the vuln affects only the rate-limiter's own security function.
Affected VersionsAll versions of @fastify/rate-limit prior to 11.2.0. This includes the legacy fastify-rate-limit package (pre-scoped npm name).
Fixed Version@fastify/rate-limit 11.2.0 (released 2026-07-29). Introduces normalizeIP() canonicalization and configurable ipv6Subnet option (default /64). No distro backports apply — this is a pure npm package.
Exposure / Install Base~812,000 weekly npm downloads. Fastify is the second-most-popular Node.js framework after Express. No Shodan/Censys fingerprint exists for this specific middleware — exposure must be inferred from npm telemetry and dependency graphs.
Disclosure Date2026-07-29 — advisory published by Matteo Collina (mcollina) via GitHub Security Advisories (GHSA-grpc-p53c-r64v).
Related CVEsCVE-2026-30827 (express-rate-limit IPv4-mapped IPv6 bypass, similar class). CVE-2026-29794 (Vikunja rate-limit bypass via spoofed headers). This is part of a 2026 wave of IPv6-aware rate-limit fixes across the Node.js ecosystem.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.3/10)

This vulnerability only weakens a defense-in-depth rate-limiting control — it does not independently achieve compromise, data access, or code execution; the attacker must still chain it with brute-force against an endpoint that *also* lacks MFA, account lockout, or CAPTCHA. The single most decisive downgrade factor is blast radius limited to individual accounts on endpoints missing secondary brute-force defenses, which narrows real-world impact well below the vendor's HIGH threshold.

HIGH Vulnerability mechanics and affected versions
HIGH Fix availability and remediation path
MEDIUM Real-world exploitability (depends on target's IPv6 exposure and secondary controls)
LOW EPSS and in-the-wild exploitation data (CVE is <48 hours old)

Why this verdict

  • Defense-in-depth weakening, not direct compromise: The vulnerability disables one layer (rate limiting) but leaves MFA, account lockout, CAPTCHA, and upstream WAF rate limits intact. An attacker who bypasses the Fastify rate limiter has *permission to try harder* — not permission to succeed.
  • IPv6 connectivity is a prerequisite that narrows exposure: Many enterprise API deployments sit behind IPv4-only internal load balancers or CDNs that canonicalize addresses upstream. The attack requires the attacker to have a routable IPv6 prefix *and* for the target to pass raw IPv6 through to Fastify — a conjunction that excludes a significant fraction of deployments.
  • Vendor's own CIA ratings are all Low: The CVSS vector explicitly rates confidentiality, integrity, and availability impact as Low. The 7.3 score is inflated by the frictionless attack-reach metrics (AV:N/AC:L/PR:N/UI:N). In a friction-adjusted model, the Low/Low/Low impact ceiling pulls the real-world severity into MEDIUM territory.
  • Role multiplier: @fastify/rate-limit is application-tier middleware deployed in Node.js web servers and API services. It is *not* a canonical high-value-role component (not a domain controller, hypervisor, identity provider, backup agent, PKI, or network edge appliance). A small fraction of Fastify apps serve as custom identity providers where rate limiting on login is security-critical, but even in that worst case the blast radius is account-level compromise — not fleet-scale, domain-scale, or supply-chain-scale. No high-value-role floor override applies.
  • No exploitation evidence or weaponized tooling specific to this CVE: While the generic IPv6 rotation technique is commodity knowledge, no threat actor has been observed targeting @fastify/rate-limit specifically. The 48-hour-old disclosure has produced no PoC repos or scanner plugins yet.

Why not higher?

The vendor's HIGH (7.3) would be appropriate if bypassing the rate limit *directly* achieved compromise — but it doesn't. The CIA impact is Low/Low/Low by the vendor's own vector. The vulnerability is a prerequisite-weakener that must be chained with brute-force against an endpoint that also lacks MFA, lockout, and CAPTCHA. Enterprise deployments typically have upstream WAF or CDN rate limits that operate independently of the Fastify middleware, further reducing the population where this vulnerability is the sole defense.

Why not lower?

A LOW or IGNORE rating would underweight the 812K weekly download footprint and the fact that the attack is unauthenticated, remotely exploitable, and requires zero user interaction. Some Fastify applications *do* rely on @fastify/rate-limit as their primary brute-force defense on login endpoints — particularly smaller teams that haven't implemented MFA or account lockout. For those deployments, this bypass is operationally significant. The fix is also trivial (npm update), so there's no reason to deprioritize it into backlog-only status.

05 · Compensating Control

What to do — in priority order.

  1. Enforce MFA on all authentication endpoints — MFA renders brute-force attacks ineffective regardless of rate-limit status. If your Fastify login endpoints lack MFA, this is your highest-priority compensating control — deploy it within the 365-day noisgate remediation window, ideally much sooner.
  2. Implement account lockout or progressive delays — Lock accounts after N failed attempts (e.g., 5 failures → 15-minute lockout). This operates independently of IP-based rate limiting and stops credential stuffing even if the rate limiter is bypassed.
  3. Add CAPTCHA or proof-of-work on sensitive endpoints — reCAPTCHA v3, hCaptcha, or Turnstile on login/OTP/reset endpoints impose per-request cost that IPv6 rotation cannot circumvent.
  4. Apply upstream rate limiting at CDN/WAF/API gateway — Cloudflare Rate Limiting, AWS WAF rate-based rules, or NGINX limit_req with IPv6 subnet awareness (/64 bucketing) will throttle traffic before it reaches Fastify. Configure your edge to normalize and subnet-mask IPv6 addresses.
  5. Pin a custom keyGenerator until you can upgrade — If you cannot immediately bump to 11.2.0, set a custom keyGenerator that normalizes IPs: keyGenerator: (req) => require('net').isIPv6(req.ip) ? req.ip.replace(/:.*/,'') : req.ip as a rough /16 mask. This is a stopgap — upgrade is the real fix.
What doesn't work
  • IP reputation blocklists — the attacker uses fresh, never-seen-before IPv6 addresses from a legitimately allocated prefix; reputation databases will not flag them.
  • Connection-level rate limiting (iptables/nftables per-IP) — the attacker rotates source IPs at Layer 3, so per-IP kernel-level limits face the same bypass unless configured with /64 prefix matching via ipset or nft sets.
  • TLS client certificate pinning — while it eliminates anonymous access, it doesn't help if the attacker has a valid client cert (e.g., in mTLS API deployments where certs are issued per-org, not per-device).
06 · Verification

Crowdsourced verification payload.

Run this on any machine with node and npm installed (no root required). It checks the installed version of @fastify/rate-limit in the current project directory. Example: cd /path/to/your/fastify-app && bash check_cve_2026_15144.sh

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_15144.sh
# Checks whether @fastify/rate-limit is vulnerable to CVE-2026-15144
# (IPv6 rate-limit bypass via address rotation / representation aliasing)
# Fixed in: @fastify/rate-limit >= 11.2.0
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PKG="@fastify/rate-limit"
FIXED="11.2.0"

# Try to find installed version
if command -v npm &>/dev/null; then
  VERSION=$(npm ls "$PKG" --json 2>/dev/null | node -e "
    const j = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
    function find(obj) {
      if (!obj) return null;
      if (obj.dependencies && obj.dependencies['$PKG']) return obj.dependencies['$PKG'].version;
      if (obj.dependencies) for (const k of Object.keys(obj.dependencies)) { const r = find(obj.dependencies[k]); if (r) return r; }
      return null;
    }
    const v = find(j);
    if (v) process.stdout.write(v); else process.exit(1);
  " 2>/dev/null) || true
fi

if [ -z "${VERSION:-}" ]; then
  # Fallback: check package-lock.json or node_modules directly
  if [ -f node_modules/@fastify/rate-limit/package.json ]; then
    VERSION=$(node -e "console.log(require('./node_modules/@fastify/rate-limit/package.json').version)" 2>/dev/null) || true
  fi
fi

if [ -z "${VERSION:-}" ]; then
  echo "UNKNOWN — $PKG not found in this project"
  exit 2
fi

# Compare versions using node's semver-compatible comparison
RESULT=$(node -e "
  const v = '$VERSION'.split('.').map(Number);
  const f = '$FIXED'.split('.').map(Number);
  for (let i = 0; i < 3; i++) {
    if (v[i] < f[i]) { console.log('VULNERABLE'); process.exit(0); }
    if (v[i] > f[i]) { console.log('PATCHED'); process.exit(0); }
  }
  console.log('PATCHED');
" 2>/dev/null)

if [ "$RESULT" = "VULNERABLE" ]; then
  echo "VULNERABLE — $PKG $VERSION is below fixed version $FIXED (CVE-2026-15144)"
  exit 1
elif [ "$RESULT" = "PATCHED" ]; then
  echo "PATCHED — $PKG $VERSION >= $FIXED"
  exit 0
else
  echo "UNKNOWN — could not compare versions"
  exit 2
fi
07 · Bottom Line

If you remember one thing.

TL;DR
This is a MEDIUM (downgraded from vendor HIGH) rate-limit bypass in @fastify/rate-limit — it weakens a defense layer but doesn't independently achieve compromise. There is no noisgate mitigation SLA for MEDIUM — go straight to the 365-day noisgate remediation SLA. That said, the fix is a one-line npm update @fastify/rate-limit to 11.2.0, so there's no reason to wait: queue it into your next scheduled dependency update cycle. If your Fastify applications protect authentication or OTP endpoints *without* MFA or account lockout, prioritize those apps first and confirm upstream WAF/CDN rate limits are active as a compensating control in the interim. For the other 90% of deployments where rate limiting is a convenience throttle rather than a security gate, treat this as routine dependency hygiene within your normal sprint cadence.

Sources

  1. GitHub Security Advisory GHSA-grpc-p53c-r64v
  2. @fastify/rate-limit Releases (v11.2.0)
  3. @fastify/rate-limit README — keyGenerator and ipv6Subnet docs
  4. freebind — IPv6 address rotation evasion tool
  5. OneUptime — How to Handle IPv6 in Rate Limiting Middleware
  6. CVE-2026-30827 — express-rate-limit IPv6 bypass (related class)
  7. HackTricks — Rate Limit Bypass Techniques
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.