Skip to content

fix: gate setup wizard endpoints behind manage_options and nonces - #1354

Open
lucadobrescu wants to merge 2 commits into
fix/aibuilder-chart-authfrom
fix/wizard-endpoint-auth
Open

fix: gate setup wizard endpoints behind manage_options and nonces#1354
lucadobrescu wants to merge 2 commits into
fix/aibuilder-chart-authfrom
fix/wizard-endpoint-auth

Conversation

@lucadobrescu

Copy link
Copy Markdown
Contributor

The setup wizard's dismiss action and step-processing endpoint could be invoked by any logged-in user — dismissal without any nonce, and steps with only a nonce — letting low-privilege users flip install state, create charts and draft pages, or trigger plugin installs. This gates the dismiss action behind manage_options plus a nonce, and the step dispatcher behind manage_options.

What changed

  • Dismiss actionadmin.php?action=visualizer_dismiss_wizard now requires manage_options and a valid nonce via check_admin_referer(), and the wizard template signs its dismiss link with wp_nonce_url(). Before: no nonce and no capability check — any authenticated user could flip the visualizer_fresh_install option and wipe visualizer_wizard_data.

  • Step dispatchervisualizer_wizard_step_process rejects non-admins with 403 after the existing nonce check. One gate covers every step: chart import, plugin install, subscribe, and draft-page creation (which also deletes all post meta of the page it updates).

Note

The internal dismissWizard( false ) call from the subscribe step intentionally skips check_admin_referer() — it is only reachable through the step dispatcher, which is already nonce- and capability-verified.

Wizard request flow

flowchart LR
    A[Wizard request] --> B{Entry point}
    B -- dismiss link --> C{Changed:<br/>manage_options?}:::changed
    B -- step AJAX --> D{Nonce valid?}
    C -- no --> X[403]
    C -- yes --> E{New:<br/>nonce valid?}:::added
    E -- no --> X
    E -- yes --> F[Update options, redirect]
    D -- no --> X
    D -- yes --> G{New:<br/>manage_options?}:::added
    G -- no --> X
    G -- yes --> H[Run wizard step]

    classDef added fill:#1a7f37,color:#fff,stroke:#116329,stroke-width:3px
    classDef changed fill:#9a6700,color:#fff,stroke:#5c3d00,stroke-width:3px,stroke-dasharray:6 3
Loading

QA

  1. WP Admin → Users → Add New: create a Contributor user and log in as them in a private window.

  2. As the contributor, visit /wp-admin/admin.php?action=visualizer_dismiss_wizard&status=1.

Expect: a 403 "You do not have permission to perform this action." page. Before this change, the same URL silently updated the option and redirected to the Visualizer dashboard.

  1. As admin, visit the same URL without a nonce.

Expect: the "link you followed has expired" nonce screen (403). Before, it dismissed the wizard.

  1. Regression — on a fresh install (or after wp option update visualizer_fresh_install 1), open WP Admin → Visualizer and complete the setup wizard, using the skip/dismiss link at the end.

Expect: the wizard completes and dismisses normally and the Chart Library loads.

@lucadobrescu
lucadobrescu marked this pull request as ready for review July 29, 2026 10:46
Co-authored-by: Cursor <cursoragent@cursor.com>
@pirate-bot

pirate-bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Plugin build for d58f689 is ready 🛎️!

Co-authored-by: Cursor <cursoragent@cursor.com>
@lucadobrescu
lucadobrescu force-pushed the fix/wizard-endpoint-auth branch from 2773045 to d58f689 Compare July 29, 2026 10:54
@Soare-Robert-Daniel Soare-Robert-Daniel added the pr-checklist-skip Allow this Pull Request to skip checklist. label Jul 29, 2026
@pirate-bot pirate-bot added the pr-checklist-complete The Pull Request checklist is complete. (automatic label) label Jul 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Secures setup wizard actions against low-privilege users and CSRF.

Changes:

  • Adds manage_options checks to dismissal and step processing.
  • Adds nonce protection to dismissal links.
  • Adds E2E coverage for dismissal authorization.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
classes/Visualizer/Module/Wizard.php Enforces capabilities and nonce validation.
templates/setup-wizard.php Signs the dismissal URL.
tests/e2e/specs/wizard-auth.spec.js Tests unauthorized and nonce-less dismissal.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +178 to +179
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json( array( 'status' => 0 ), 403 );

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

classes/Visualizer/Module/Wizard.php:179

  • The new authorization gate for the step dispatcher is not covered: the added E2E tests only exercise visualizer_dismiss_wizard, while the existing AJAX test covers only the administrator success path. Add a valid-nonce contributor request to visualizer_wizard_step_process and assert a 403 plus no chart/page/option side effects; otherwise the main privilege-escalation fix can regress without these tests failing.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json( array( 'status' => 0 ), 403 );

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

Labels

pr-checklist-complete The Pull Request checklist is complete. (automatic label) pr-checklist-skip Allow this Pull Request to skip checklist.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants