Skip to content

Reflected XSS via evf_toast_type query parameter (Patchstack #35058) #1663

Description

@rajatgautam755421

Summary

Reported via Patchstack (report ID 35058), CVSS 7.1, unauthenticated.

window.evfShowToast() in assets/js/admin/admin.js (and the loaded admin.min.js build) concatenates its type argument directly into a class attribute inside an HTML string, which is then parsed into live DOM nodes via jQuery. The only existing guard was type = type || 'info', which does nothing to validate the content of a truthy string.

On every admin screen the plugin registers, the bootstrap in admin.js reads evf_toast_type straight from the URL query string with no validation and passes it to evfShowToast():

var toastType = urlParams.get('evf_toast_type') || 'success';
...
window.evfShowToast(atob(decodeURIComponent(toastMessage)), toastType, 5000);

Impact

An attacker with no account can craft a single link. Anyone who opens it while logged in with access to the Everest Forms admin menu gets arbitrary JavaScript executed in their session (nonces, cookies) on the wp-admin origin — no prior site state, no form, no entry required.

PoC

/wp-admin/admin.php?page=evf-entries&evf_toast=WFNT&evf_toast_type=x%22%3E%3Cimg%20src%3Dx%20onerror%3Dalert(document.domain)%3E

alert(document.domain) fires immediately on page load.

Root cause

The type value is never validated against the small, fixed set of values the toast system actually supports (success, error, info, warning) before being concatenated into markup.

Fix

Branch fix/xss-toast-type-reflected (based on pre-develop), commit 22a9bf7: whitelist type inside evfShowToast() itself against ['success', 'error', 'info', 'warning'], falling back to 'info' for anything else. This is the single shared function every caller (including the vulnerable URL-driven one) routes through, so it closes the injection point regardless of where the value originates. Applied identically to admin.min.js.

Verified every existing call site in both the free and pro codebases only ever passes one of the four whitelisted literals, so this is a behavior-preserving fix for all legitimate usage.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions