← Back to Feed CACHED · 2026-10-14 10:16:52 · CACHE_KEY CVE-2026-85097
CVE-2026-85097 · CWE-434 · Disclosed 2026-10-08

Bricksforge Pro Forms Unauthenticated Arbitrary File Upload to RCE

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

Someone left the back door unlocked and propped open with a sign saying 'free webshells inside'

CVE-2026-85097 is an unauthenticated arbitrary file upload vulnerability in the Bricksforge plugin for WordPress (an addon for the Bricks visual page builder). The flaw lives in the Pro Forms module's temporaryFileUploads handling: Bricksforge validates a file's MIME type at initial upload but then blindly trusts the client-supplied url field during form submission. An attacker obtains a nonce from the unauthenticated bricksforge_regenerate_nonce AJAX endpoint, uploads a GIF/PHP polyglot that passes the MIME check, then submits a form where the temporaryFileUploads parameter pairs the validated image path with a .php destination URL. The server writes the polyglot's contents to the PHP path and Apache/Nginx executes the embedded code — full webshell, no credentials required. Affected: Bricksforge ≤ 3.1.8.9. Fixed: 3.1.8.10.

The vendor severity of CRITICAL 9.8 is dead-on — arguably conservative, since Patchstack scores it 10.0. Every prerequisite is attacker-supplied: the nonce endpoint requires no auth, the MIME check is trivially bypassed with a polyglot, and the file-write target is entirely client-controlled. There is zero friction in the chain. Patchstack observed exploitation before public disclosure (October 7, 21:47 UTC — the advisory dropped October 8), 63 unique source IPs are actively scanning, and a Python PoC from *RootMantap* hit GitHub on October 14. For any site running Bricksforge with Pro Forms active, this is a walk-in-the-front-door RCE.

"Unauthenticated RCE via polyglot file upload — actively exploited, patch today."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Nonce acquisition

The attacker sends an unauthenticated POST to wp-admin/admin-ajax.php?action=bricksforge_regenerate_nonce. The endpoint has no capability check — it returns a fresh, valid WordPress nonce to anyone who asks. This nonce is required for subsequent API calls but costs the attacker one HTTP request and zero credentials.
Conditions required:
  • Target runs WordPress with Bricksforge ≤ 3.1.8.9 active
  • The bricksforge_regenerate_nonce AJAX action is registered (always is when plugin is active)
Where this breaks in practice:
  • None — endpoint is unconditionally available
Detection/coverage: WAF rules can flag unauthenticated calls to bricksforge_regenerate_nonce. Patchstack vPatching blocks this.
STEP 02

GIF/PHP polyglot upload

Using the acquired nonce, the attacker uploads a file to the temporary upload directory (/wp-content/uploads/bricksforge/tmp/). The file is a valid GIF image whose trailing bytes contain <?php code. Because Bricksforge validates the MIME type at upload time and the file genuinely satisfies image/gif, it passes. Tools like *RootMantap/CVE-2026-85097* automate polyglot generation.
Conditions required:
  • Valid nonce from step 1
  • Bricksforge Pro Forms module is active on at least one page
Where this breaks in practice:
  • None — polyglot generation is trivial and well-documented
Detection/coverage: File integrity monitoring (FIM) on the uploads directory can catch unexpected file creation. ModSecurity 930120 rule family may flag polyglot content.
STEP 03

Form submission with mismatched extension

The attacker POSTs to /wp-json/bricksforge/v1/form_submit (or admin-ajax.php?action=bricksforge_form_submit) with a temporaryFileUploads array. The file field points to the uploaded GIF path; the url field ends in .php. Bricksforge does not validate or sanitize the url field — it uses it as the destination path and writes the polyglot contents there. Attackers rotate extensions (.php, .php5, .php7, .phtml, .pht) and use URL-encoding or case manipulation to evade naive blocklists.
Conditions required:
  • Valid nonce
  • Polyglot file present in tmp directory
Where this breaks in practice:
  • A WAF rule specifically matching image-path + PHP-destination pairs would block this, but no default WordPress WAF ships such a rule
Detection/coverage: Log analysis for POST to form_submit endpoints with temporaryFileUploads containing .php in the url field. Patchstack RapidMitigate covers this.
STEP 04

Webshell execution

The attacker requests the newly created .php file at its predictable URL under /wp-content/uploads/. The web server executes the PHP code, giving the attacker arbitrary command execution as the web server user (www-data / nginx / apache). From here, standard post-exploitation applies: database credential extraction from wp-config.php, lateral movement, crypto-mining, SEO spam injection, or pivot into internal networks if the web server has internal connectivity.
Conditions required:
  • PHP execution is enabled in the uploads directory (default on nearly all WordPress hosts)
Where this breaks in practice:
  • Disabling PHP execution in uploads via .htaccess or Nginx config blocks this step, but this is not a WordPress default
Detection/coverage: Unexpected PHP files in uploads directories. Web server access logs showing GET/POST to .php files under /wp-content/uploads/bricksforge/. EDR or HIDS alerts on www-data spawning shells.
03 · Compensating Control

1
CRITICAL 9.8→HIGH 7.5
SEVERITY REDUCED
Disable PHP execution in uploads directory — Add php_flag engine off to /wp-content/uploads/.htaccess (Apache) or location ~* /wp-content/uploads/.*\.php$ { deny all; } to your Nginx config. This breaks the final step of the chain — the polyglot is written but never executed. Deploy within 3 days per noisgate mitigation SLA for CRITICAL findings. This is the single most effective compensating control if you cannot patch immediately.
2
CRITICAL 9.8→HIGH 7.0
SEVERITY REDUCED
Block bricksforge_regenerate_nonce at the WAF/reverse proxy — Add a WAF rule (ModSecurity, Cloudflare, Sucuri, or Patchstack RapidMitigate) to deny unauthenticated POST requests to admin-ajax.php with action=bricksforge_regenerate_nonce. Without a valid nonce, the subsequent form submission fails. Deploy within 3 days. Note: this may break legitimate Bricksforge form functionality for anonymous visitors — test in staging first.
3
CRITICAL 9.8→LOW 2.0
SEVERITY REDUCED
Deploy Patchstack RapidMitigate virtual patch — Patchstack released a virtual patch specifically for CVE-2026-85097 that blocks exploitation at the traffic layer without modifying plugin code. If you use Patchstack, enable it immediately. This addresses the full chain. Deploy within 3 days.
4
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Deactivate Bricksforge Pro Forms module — If Pro Forms is not business-critical, deactivate it in the Bricksforge settings. The vulnerable code path is only reachable when Pro Forms is active. This eliminates the attack surface entirely until you can patch to 3.1.8.10+. Deploy within 3 days.
5
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Update to Bricksforge 3.1.8.10 or later — The definitive fix. Version 3.1.8.10 validates the url field in temporaryFileUploads and rejects mismatched extensions. Current latest is 4.0.1. Apply within 90 days per noisgate remediation SLA, but given active exploitation, treat this as immediate — patch within hours if possible.
What doesn't work
  • WordPress built-in file type checking (DISALLOW_UNFILTERED_UPLOADS) — this constant only affects the media library uploader and admin-side uploads. Bricksforge's Pro Forms upload path is a custom AJAX/REST handler that does not honor this constant.
  • Generic upload size limits — the polyglot payload is tiny (a few hundred bytes appended to a valid GIF header). Size restrictions will not block it.
  • Cloudflare 'Under Attack Mode' — this adds a JavaScript challenge for browsers but does not block server-to-server POST requests from automated exploit scripts that handle the challenge or target the REST API directly.
  • Disabling XML-RPC — this vulnerability uses the REST API and admin-ajax.php, not XML-RPC. Disabling XML-RPC provides no protection.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationActive. Patchstack observed exploitation beginning 2026-10-07 21:47 UTC — one day *before* public disclosure. 63 unique source IPs identified; 6 IPs account for ~46% of traffic. Infrastructure spans datacenters, cloud, VPN/proxy, and residential ISPs. (Patchstack, SecurityWeek)
Proof-of-conceptPublic. Python PoC by RootMantap/CVE-2026-85097 published 2026-10-14, indexed on Sploitus. Additional PoC references in SecureWithUmer/CVE-2026-PoCs. Not yet indexed on pocindex.io.
EPSS0.00312 (31st percentile). Low EPSS reflects model lag — the CVE is only 6 days old and EPSS has not yet ingested the active-exploitation signal. Treat this score as stale.
KEV statusNot listed as of 2026-10-14. Given confirmed in-the-wild exploitation, KEV addition is probable in the near term.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — 9.8 (Wordfence). Patchstack scores 10.0. Network-accessible, no authentication, no user interaction, full CIA impact. The vector is accurate.
Affected versionsBricksforge ≤ 3.1.8.9 (all versions with Pro Forms). Parent theme: Bricks Builder (premium, estimated 30,000–50,000 active sites based on addon install proxies). Bricksforge is a third-party premium addon — no WordPress.org listing, so exact install count is unavailable.
Fixed version3.1.8.10 (released ~2026-10-08). Current latest is 4.0.1 (2026-10-09).
Scanning / exposureAll affected sites are internet-facing WordPress installations by nature. Attackers are rotating PHP extensions (.php, .php5, .php7, .php8, .phtml, .pht, .phps) and using case manipulation / URL-encoding to evade WAF rules. 44 IPs sent identical payloads within seconds; 3 IPs tested 25+ extension variations.
Disclosure date2026-10-08 (Patchstack advisory). Pre-disclosure exploitation confirmed from 2026-10-07.
Reporting researcherd.v4n_s3c (credited on CVE record). Patchstack performed the technical analysis and coordinated disclosure.

Sources.

  1. Patchstack Advisory
  2. The Hacker News Coverage
  3. SOCRadar Analysis
  4. SecurityWeek Report
  5. RootMantap PoC (Sploitus)
  6. GBHackers Technical Writeup
  7. DEV Community Analysis
  8. SC World News
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Why this verdict

  • Zero-friction attack chain: Every prerequisite is attacker-supplied. The nonce endpoint is unauthenticated, the MIME check is bypassed with a trivial polyglot, and the destination path is entirely client-controlled. There is no step in this chain that requires credentials, user interaction, or special network position.
  • Active pre-disclosure exploitation: Patchstack telemetry confirms exploitation beginning 2026-10-07, *before* the advisory. 63 source IPs are scanning. This is not theoretical — sites are being popped right now.
  • Public weaponized PoC: RootMantap's Python exploit dropped the same day as this assessment (2026-10-14). The barrier to mass exploitation is a pip install requests away.
  • Internet-facing by definition: WordPress sites run on the public internet. There is no 'internal-only deployment' friction to discount. Every Bricksforge installation with Pro Forms is reachable.
  • Role multiplier: Bricksforge is a WordPress CMS plugin, not a canonical high-value-role component (not an IdP, hypervisor, DC, or PKI system). The blast radius per compromised site is host-level: webshell → wp-config.php database credentials → site data (PII, payment data on e-commerce sites) → potential pivot to internal network if the web server has LAN connectivity. For WordPress hosting providers or agencies running multi-tenant WordPress, a single compromised host can cascade to dozens of client sites — pushing toward fleet-scale impact in that deployment model. The host-level blast radius does not override the CRITICAL floor set by the frictionless, actively-exploited, unauthenticated RCE chain.
  • Install base limiter (insufficient to downgrade): Bricksforge is a niche premium addon (estimated 30K–50K sites vs. Elementor's 10M). This limits the *population* at risk but does not reduce the *severity per affected host*. CVSS scores individual-host impact, and for affected sites the impact is total compromise.

Why not higher?

The vendor score of 9.8 is already near-maximum. Patchstack's 10.0 reflects the nonce endpoint removing the last authentication barrier. The difference is academic — both map to CRITICAL. There is no meaningful argument for scoring higher than 9.8 under the CVSS:3.1 vector provided.

Why not lower?

Downgrading would require friction in the attack chain, and there is none. The attacker needs no credentials, no user interaction, no special network position, and no insider knowledge. The nonce is freely dispensed, the polyglot is trivial, and the file-write path is client-controlled. Active in-the-wild exploitation and a public PoC eliminate any residual argument for 'theoretical only.' The small install base limits *exposure* but not *severity* — CVSS and this assessment rate per-host impact, not population size.

06 · Verification

Crowdsourced verification payload.

Run this script on each WordPress host (or via SSH from your management server) as any user with read access to the WordPress installation directory. Usage: bash check_cve_2026_85097.sh /var/www/html (pass the WordPress root path as the first argument). No root privileges required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-85097 Checker — Bricksforge Unauthenticated File Upload → RCE
# Usage: bash check_cve_2026_85097.sh /path/to/wordpress
# Exit codes: 0 = PATCHED/not affected, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

WP_ROOT="${1:-/var/www/html}"
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/bricksforge"
MAIN_FILE="$PLUGIN_DIR/bricksforge.php"

# Check if Bricksforge is installed
if [ ! -d "$PLUGIN_DIR" ]; then
  echo "PATCHED — Bricksforge plugin not found at $PLUGIN_DIR. Not affected."
  exit 0
fi

if [ ! -f "$MAIN_FILE" ]; then
  echo "UNKNOWN — Bricksforge directory exists but main file not found."
  exit 2
fi

# Extract version from plugin header
VERSION=$(grep -i '^[[:space:]]*\*[[:space:]]*Version:' "$MAIN_FILE" | head -1 | sed 's/.*Version:[[:space:]]*//' | tr -d '[:space:]')

if [ -z "$VERSION" ]; then
  echo "UNKNOWN — Could not extract Bricksforge version from $MAIN_FILE."
  exit 2
fi

echo "Detected Bricksforge version: $VERSION"

# Version comparison: vulnerable if <= 3.1.8.9
# Use sort -V for natural version sorting
FIXED="3.1.8.10"
OLDEST=$(printf '%s\n%s' "$VERSION" "$FIXED" | sort -V | head -1)

if [ "$VERSION" = "$FIXED" ] || [ "$OLDEST" = "$FIXED" ]; then
  echo "PATCHED — Bricksforge $VERSION >= $FIXED. CVE-2026-85097 is fixed."
  exit 0
else
  echo "VULNERABLE — Bricksforge $VERSION < $FIXED. CVE-2026-85097 applies."
  # Additional check: look for signs of compromise
  UPLOADS="$WP_ROOT/wp-content/uploads/bricksforge/tmp"
  if [ -d "$UPLOADS" ]; then
    PHP_COUNT=$(find "$UPLOADS" -name '*.php' -o -name '*.php5' -o -name '*.php7' -o -name '*.php8' -o -name '*.phtml' -o -name '*.pht' 2>/dev/null | wc -l)
    if [ "$PHP_COUNT" -gt 0 ]; then
      echo "WARNING — Found $PHP_COUNT PHP file(s) in $UPLOADS — possible exploitation artifact!"
      find "$UPLOADS" -name '*.php*' -o -name '*.phtml' -o -name '*.pht' 2>/dev/null
    fi
  fi
  exit 1
fi