← Back to Feed CACHED · 2026-06-21 09:08:26 · CACHE_KEY CVE-2026-4020
CVE-2026-4020 · CWE-200 · Disclosed 2026-03-31

Gravity SMTP <= 2

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

An open filing cabinet at the front door labeled `wp-json` — and the SendGrid keys are in the top drawer

Gravity SMTP registers a REST route at /wp-json/gravitysmtp/v1/tests/mock-data whose permission_callback is hardcoded to __return_true. Any unauthenticated visitor who appends ?page=gravitysmtp-settings gets back ~365 KB of JSON: PHP version and extensions, web server, document root, DB engine/version, WordPress core version, every active plugin and theme with versions, DB table prefix, and — crucially — the API tokens and credentials configured for whatever mail transport the site uses (SendGrid, Mailgun, SES, SMTP2GO, Postmark, etc.). Affects all versions ≤ 2.1.4; fixed in 2.1.5.

Vendor's HIGH (7.5, C:H only) is technically defensible — direct CIA impact is confidentiality. In practice it understates the chain. The disclosed connector_data blob includes live transport credentials, which means this is not just recon; it's a one-shot credential leak that pivots into the victim's email infrastructure (sender reputation hijack, phishing-as-the-brand, password-reset interception). Wordfence has blocked 17M+ exploit attempts; CrowdSec flipped it to background-noise status by June 1, 2026, with 412 distinct attacker IPs and 83% of observed intent classified as infrastructure takeover. We nudge to 8.2.

"Unauth GET that hands you the System Report plus configured SMTP API keys. 17M+ exploit attempts blocked. Patch now, then rotate every key the plugin touched."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Identify Gravity SMTP installs

Mass-scan WordPress targets for the plugin's presence — either by hitting the REST namespace /wp-json/gravitysmtp/v1/ and reading the 200/404, or by fingerprinting plugin assets under /wp-content/plugins/gravitysmtp/. Trivially automated with httpx, nuclei, or any WordPress recon framework.
Conditions required:
  • Internet-reachable WordPress site
  • Gravity SMTP plugin installed and active
  • REST API not blocked by WAF rule
Where this breaks in practice:
  • Sites behind Cloudflare WAF Managed Rules may block the discovery probe
  • REST API disabled via disable-json-api or similar plugin
Detection/coverage: Wordfence and Patchstack signatures fire on the request URI; nuclei template CVE-2026-4020 available publicly
STEP 02

Hit the unauthenticated endpoint

Issue an HTTP GET to https://target/wp-json/gravitysmtp/v1/tests/mock-data?page=gravitysmtp-settings. The permission_callback returns true unconditionally, so no nonce, no cookie, no auth header is required. Response is ~365 KB of JSON.
Conditions required:
  • Endpoint reachable
  • Plugin version ≤ 2.1.4
Where this breaks in practice:
  • Cloudflare/Sucuri/Wordfence virtual patch can drop the request
  • Some hosts rate-limit /wp-json/ aggressively
Detection/coverage: Atomic Edge and pentest-tools.com published PoCs; signature is a simple URI match
STEP 03

Parse the System Report

Extract connector_data from the JSON. Each configured transport carries its credentials in cleartext — SendGrid API key, Mailgun domain+key, AWS SES access_key/secret, SMTP2GO token, raw SMTP user/pass, etc. Also harvest plugin/theme inventory for follow-on CVE pivoting.
Conditions required:
  • Site has at least one mail transport configured
  • Credentials were entered through the plugin UI (not constants in wp-config.php)
Where this breaks in practice:
  • Sites using only the default wp_mail() SMTP fallback have no API keys to leak
  • Rare hardened setups inject keys via env vars not stored in plugin options
Detection/coverage: No detection at this step — parsing happens off-target
STEP 04

Weaponize the stolen credentials

Use SendGrid/Mailgun/SES API keys to send phishing from the victim's verified domain, bypassing SPF/DKIM/DMARC because the mail is genuinely signed. Or use the credentials to enumerate the victim's mail provider tenant for further abuse. Reported intent in 83% of CrowdSec-observed cases is downstream infrastructure takeover.
Conditions required:
  • Stolen key still valid (not rotated)
  • Provider tenant not IP-restricted
Where this breaks in practice:
  • SendGrid/Mailgun anomaly detection may rate-limit a new sending pattern
  • AWS SES sandbox accounts cap sending to verified addresses
Detection/coverage: Provider-side anomaly alerts; outbound spam reports; DMARC RUF reports if monitored
STEP 05

Pivot via the leaked plugin inventory

The leaked plugin/theme/version list lets the attacker query a CVE database for known-vulnerable companions on the same host. Common follow-on: chain into an RCE in an outdated form/builder/SEO plugin, or a known auth bypass, for full WordPress compromise.
Conditions required:
  • Site runs at least one other vulnerable plugin
  • No virtual patching layer
Where this breaks in practice:
  • Sites on managed WordPress hosts (WP Engine, Kinsta, Pressable) get automatic virtual patches
Detection/coverage: Depends on the follow-on CVE; not detectable from the disclosure itself
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusActive mass exploitation since 2026-05-27 per CrowdSec; 17M+ attempts blocked by Wordfence since early May 2026
Attacker telemetry412 distinct source IPs May 27–Jun 1, 2026 (FR/NL/US cloud), classified as Background Noise by Jun 1 — fully commoditized
Public PoCAtomic Edge PoC, pentest-tools.com module, and public nuclei template — single-request curl-grade exploit
EPSS0.0298 (~~3rd percentile~~) — *score is stale*; real-world exploitation already saturating, expect EPSS to spike
KEV statusNot yet KEV-listed as of 2026-06-21, but meets the mass-exploitation criterion; expect addition
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N — confidentiality-only, but C:H is fair given API key leak
Affected versionsGravity SMTP ≤ 2.1.4 (all releases up to and including)
Fixed version2.1.5 — adds capability check to permission_callback
Install base~100,000 active installs of Gravity SMTP per WordPress.org plugin directory; victim mix 55% commerce / 39% SOHO (CrowdSec)
Disclosed2026-03-31 (Wordfence Threat Intelligence advisory; GHSA-jxfc-8wcq-xxcg)
DiscovererReported via the Wordfence Bug Bounty program; vendor Gravity Forms LLC
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (8.2/10)

HIGH is the correct bucket because this is a one-request, unauthenticated, internet-reachable leak of live third-party mail-provider API credentials, and exploitation is already commoditized at mass-scan scale (17M+ Wordfence blocks, 412 attacker IPs). The single decisive factor is the credential-leak component of the exposed System Report — this is not generic info disclosure, it is a credential theft primitive against a ~100k-install plugin under active mass exploitation.

HIGH Active exploitation and leaked content
HIGH Affected version range and fix
MEDIUM Share of installs with API-key-bearing transports configured

Why this verdict

  • Zero friction on the chain: unauthenticated, single GET, no nonce, no UA filtering, no rate-limit by default. The vendor's 7.5 already assumes AV:N/PR:N/UI:N — this is the realistic case, not the worst case.
  • The blob contains credentials, not just fingerprints. SendGrid/Mailgun/SES tokens give the attacker *signed* outbound email from the victim's domain, which bypasses SPF/DKIM/DMARC and is worth more on the criminal market than the WordPress host itself.
  • Mass exploitation is here, not theoretical. 17M+ blocked attempts (Wordfence), 412 attacker IPs in 5 days (CrowdSec), public nuclei template. EPSS of 0.0298 is stale and will spike.
  • Role multiplier: Gravity SMTP's role is mail-transport credential storage. ≥10% of installs occupy this 'secret-bearing' role *by definition of installing the plugin*. The high-value-role outcome (provider-tenant takeover, brand-spoofed phishing) is the typical outcome, not the edge case — that floors the verdict at HIGH.
  • Why not CRITICAL: the primitive does not produce code execution on the WordPress host itself, and impact is confined to outbound email provider and stale recon data. Pivot to RCE requires a separate vulnerable plugin on the same host.

Why not higher?

Direct impact is confidentiality only — no code execution, no integrity write, no service denial on the WordPress instance itself. CRITICAL would imply fleet- or domain-scale takeover of the WordPress host, which requires a chained second CVE. The leaked credentials are damaging but bounded to whichever mail-provider tenant they unlock.

Why not lower?

MEDIUM would imply low real-world exploitability or non-sensitive disclosure. Neither applies: the chain is a single unauthenticated GET, the disclosed data includes live third-party API keys, and there are 17M+ logged exploit attempts in the wild. Downgrading would mis-rank this against genuinely low-noise info-disclosure bugs.

05 · Compensating Control

What to do — in priority order.

  1. Update Gravity SMTP to 2.1.5 across every WordPress estate host within 3 days — This is the only true fix. The patch adds a proper capability check to the REST permission_callback. Per noisgate mitigation SLA (HIGH = 30 days) we would normally allow 30 days, but active mass exploitation overrides — patch within 3 days.
  2. Rotate every credential the plugin ever stored — Assume disclosure. Rotate SendGrid/Mailgun/SES/Postmark/SMTP2GO API keys, raw SMTP passwords, and any reply-to webhook tokens. Do this *before* upgrading on any host that has been internet-reachable since 2026-03-31. Patching does not invalidate already-stolen keys.
  3. Drop the route at the edge / WAF until upgraded — Add a deny rule on the URI pattern ^/wp-json/gravitysmtp/v1/tests/mock-data at Cloudflare, AWS WAF, F5, or NGINX. Effective within minutes across the fleet and covers slow-to-patch sites.
  4. Review mail-provider tenant logs from 2026-03-31 onward — In SendGrid/Mailgun/SES, look for sends from unexpected source IPs or unusual send volumes. If found, treat the tenant as compromised, not just the WordPress site.
  5. Block known attacker source IPs at the edge — Pull CrowdSec community blocklist or GreyNoise tags for CVE-2026-4020 scanners; the population is small (~400 IPs) and concentrated in cloud ASNs FR/NL/US.
What doesn't work
  • Disabling xmlrpc.php — this CVE is in the WP REST API, not XML-RPC.
  • Forcing wp-admin behind HTTP basic auth — the vulnerable endpoint is under /wp-json/, not /wp-admin/.
  • Relying on DISALLOW_FILE_EDIT or admin lockdown plugins — the bug requires no admin session at all.
  • Rotating WordPress admin passwords alone — the leak is provider API keys, not WP credentials.
06 · Verification

Crowdsourced verification payload.

Run this from an auditor workstation (not the target) against each WordPress host you own. Invoke as ./check-cve-2026-4020.sh https://site.example.com. No credentials needed — the test exercises the same unauthenticated path an attacker would.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate verification — CVE-2026-4020 (Gravity SMTP <= 2.1.4)
# Usage: ./check-cve-2026-4020.sh https://target.example.com
# Exits: 0 PATCHED | 1 VULNERABLE | 2 UNKNOWN
set -u

TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
  echo "Usage: $0 https://target" >&2; exit 2
fi

UA="noisgate-check/1.0"
URL="${TARGET%/}/wp-json/gravitysmtp/v1/tests/mock-data?page=gravitysmtp-settings"

# 1. Probe the vulnerable endpoint.
RESP=$(curl -sk -A "$UA" -o /tmp/gsmtp_$$.json -w '%{http_code} %{size_download}' --max-time 20 "$URL") || {
  echo "UNKNOWN ($TARGET) — network error"; rm -f /tmp/gsmtp_$$.json; exit 2;
}
CODE=$(echo "$RESP" | awk '{print $1}')
SIZE=$(echo "$RESP" | awk '{print $2}')

# 2. Decide.
if [[ "$CODE" == "200" && "$SIZE" -gt 50000 ]]; then
  if grep -qE 'connector_data|system_report|gravitysmtp' /tmp/gsmtp_$$.json; then
    echo "VULNERABLE ($TARGET) — endpoint returned ${SIZE}B of System Report JSON"
    rm -f /tmp/gsmtp_$$.json; exit 1
  fi
fi

if [[ "$CODE" == "401" || "$CODE" == "403" ]]; then
  echo "PATCHED ($TARGET) — endpoint returned $CODE"
  rm -f /tmp/gsmtp_$$.json; exit 0
fi

if [[ "$CODE" == "404" ]]; then
  echo "PATCHED ($TARGET) — plugin not installed or REST route absent"
  rm -f /tmp/gsmtp_$$.json; exit 0
fi

echo "UNKNOWN ($TARGET) — HTTP $CODE, ${SIZE}B (inspect /tmp/gsmtp_$$.json manually)"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
This is active, commoditized, single-request credential theft against a ~100k-install WordPress plugin — treat it like an in-progress incident, not a Patch Tuesday item. Per noisgate mitigation SLA for HIGH (≤30 days), the baseline mitigation deadline would be 30 days, but active mass exploitation overrides that to immediate, within hours: deploy a WAF deny rule on ^/wp-json/gravitysmtp/v1/tests/mock-data across the fleet by end-of-day Monday and rotate every SendGrid/Mailgun/SES/SMTP credential the plugin stored before the close of business. The noisgate remediation SLA for HIGH is ≤180 days, but for this CVE compress to ≤7 days: roll Gravity SMTP 2.1.5 to all hosts, then audit mail-provider tenant logs back to 2026-03-31 for unauthorized sends and treat any anomalous activity as a confirmed tenant compromise.

Sources

  1. GitHub Security Advisory GHSA-jxfc-8wcq-xxcg
  2. CrowdSec — CVE-2026-4020 Vulntracking Report
  3. The Hacker News — Gravity SMTP exploit coverage
  4. Atomic Edge — PoC walkthrough
  5. pentest-tools.com — exploit module
  6. SentinelOne Vulnerability DB
  7. Managed-WP advisory (2026-03-31)
  8. The Next Web — 100k WordPress sites at risk
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.