Skip to content

Conversation

@Akhill2020
Copy link
Contributor

@Akhill2020 Akhill2020 commented Dec 1, 2025

Description: We got an message regarding IDOR vulnerability from patchstack, in this if any calendar is private assign still in ajax request someone can pass the private calendar ID and get the HTML for this private calendars events which is now fix by adding permission check and check for longed in user if the calendar is set to private for public it is working as it is.

Clickup: https://app.clickup.com/t/86d135nbm

Summary by CodeRabbit

  • Bug Fixes

    • Added security validation to calendar grid and list AJAX handlers to verify calendars exist and enforce user permissions before displaying content.
    • Enforced status-based access control for published, private, draft, and pending calendars; improved JSON error responses when access is denied or calendar is not found.
  • Chores

    • Bumped release to 3.5.10 and added changelog entry noting an IDOR fix.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

Adds server-side security validation to two AJAX calendar view handlers: both now validate the calendar post exists and is of type calendar, and enforce user permissions/status checks before rendering; package version and changelog were also updated.

Changes

Cohort / File(s) Change Summary
AJAX Security: Grid & List handlers
includes/calendars/views/default-calendar-grid.php, includes/calendars/views/default-calendar-list.php
Adds post existence and post_type == 'calendar' checks and enforces access control. Grid handler returns JSON error if post missing/type mismatch or user lacks view permission; List handler enforces status-based rules (publish allowed; private requires login + read_post; other non-published statuses require read_post).
Metadata: Version bump
package.json
Bumps package version from 3.5.9 to 3.5.10.
Docs: Changelog
readme.txt
Adds changelog entry for v3.5.10 noting an IDOR fix; formatting/spacing updated around entries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review the permission branching in default-calendar-list.php for correct capability checks across statuses.
  • Confirm the grid handler's view-permission check aligns with existing authorization patterns.
  • Sanity-check JSON error formats for consistency with other AJAX responses.
  • Minor review of version bump and readme entry.

Suggested reviewers

  • rosinghal

Poem

🐰 I hopped through code to check each gate,

No stray post through the calendar gate.
Grid and list now guarded and neat,
Securely rendered, every month complete. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'IDOR vulnerability fix' directly corresponds to the main objective and changes in the PR, which add security validation to prevent Insecure Direct Object Reference attacks on private calendars.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-idor-vulnarability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
includes/calendars/views/default-calendar-grid.php (1)

664-669: Redundant login check for private calendars.

The is_user_logged_in() check is redundant because current_user_can('read_post', $id) already returns false for logged-out users when the post is private.

Apply this diff to simplify the logic:

 } elseif ($post->post_status === 'private') {
-	// Private calendar - check if user has permission
-	if (!is_user_logged_in() || !current_user_can('read_post', $id)) {
+	// Private calendar - check if user has permission
+	if (!current_user_can('read_post', $id)) {
 		wp_send_json_error('You do not have permission to view this calendar.');
 		return;
 	}
includes/calendars/views/default-calendar-list.php (1)

791-796: Redundant login check for private calendars.

The is_user_logged_in() check is redundant because current_user_can('read_post', $id) already returns false for logged-out users when the post is private.

Apply this diff to simplify the logic:

 } elseif ($post->post_status === 'private') {
-	// Private calendar - check if user has permission
-	if (!is_user_logged_in() || !current_user_can('read_post', $id)) {
+	// Private calendar - check if user has permission
+	if (!current_user_can('read_post', $id)) {
 		wp_send_json_error('You do not have permission to view this calendar.');
 		return;
 	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb600c4 and 12c8fe3.

📒 Files selected for processing (2)
  • includes/calendars/views/default-calendar-grid.php (1 hunks)
  • includes/calendars/views/default-calendar-list.php (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: build
includes/calendars/views/default-calendar-list.php

[error] 1-1: Prettier formatting check failed on this file. Run 'prettier --write' to fix code style issues.

includes/calendars/views/default-calendar-grid.php

[error] 1-1: Prettier formatting check failed on this file. Run 'prettier --write' to fix code style issues.

🔇 Additional comments (1)
includes/calendars/views/default-calendar-list.php (1)

779-803: LGTM! Effective IDOR vulnerability fix.

The security validation properly addresses the reported IDOR vulnerability by enforcing access control based on post status and user capabilities. The implementation correctly uses WordPress core functions and follows the platform's security model.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
includes/calendars/views/default-calendar-grid.php (2)

645-682: IDOR fix looks correct, but consider adding nonce verification for CSRF protection.

The permission checks properly address the IDOR vulnerability by validating post existence, type, and user capabilities before rendering. However, this AJAX handler lacks nonce verification, which is a WordPress security best practice for AJAX endpoints to prevent CSRF attacks.

Consider adding nonce verification:

 public function draw_grid_ajax()
 {
     if (isset($_POST['month']) && isset($_POST['year']) && isset($_POST['id'])) {
+        // Verify nonce for CSRF protection
+        if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'simcal_default_calendar')) {
+            wp_send_json_error('Security check failed.');
+            return;
+        }
+
         $month = absint($_POST['month']);
         $year = absint($_POST['year']);
         $id = absint($_POST['id']);

Note: This would require passing a nonce from the JavaScript side when making the AJAX request.


662-676: Consider refactoring to eliminate the empty if-block.

The empty if block for published status is functional but could be cleaner using early return or restructured conditions.

-       // Check if post is published (public) or user has permission to read it
-       if ($post->post_status === 'publish') {
-           // Public calendar - allow access
-       } elseif ($post->post_status === 'private') {
-           // Private calendar - check if user has permission
-           if (!is_user_logged_in() || !current_user_can('read_post', $id)) {
-               wp_send_json_error('You do not have permission to view this calendar.');
-               return;
-           }
-       } else {
-           // Draft, pending, or other status - check if user has permission
-           if (!current_user_can('read_post', $id)) {
-               wp_send_json_error('You do not have permission to view this calendar.');
-               return;
-           }
-       }
+       // Check if user has permission to view the calendar
+       if ($post->post_status !== 'publish') {
+           // Private calendars require login
+           if ($post->post_status === 'private' && !is_user_logged_in()) {
+               wp_send_json_error('You do not have permission to view this calendar.');
+               return;
+           }
+           // Non-public calendars require read capability
+           if (!current_user_can('read_post', $id)) {
+               wp_send_json_error('You do not have permission to view this calendar.');
+               return;
+           }
+       }
includes/calendars/views/default-calendar-list.php (1)

773-809: IDOR fix correctly mirrors the grid view implementation.

The permission checks are consistent with the grid view handler, properly addressing the IDOR vulnerability. The same recommendations apply:

  1. Consider adding nonce verification for CSRF protection
  2. The empty if block for publish status could be refactored

Apply the same nonce verification pattern suggested for the grid view:

 public function draw_list_ajax()
 {
     if (isset($_POST['ts']) && isset($_POST['id'])) {
+        // Verify nonce for CSRF protection
+        if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'simcal_default_calendar')) {
+            wp_send_json_error('Security check failed.');
+            return;
+        }
+
         $ts = absint($_POST['ts']);
         $id = absint($_POST['id']);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12c8fe3 and dfaefb1.

📒 Files selected for processing (4)
  • includes/calendars/views/default-calendar-grid.php (1 hunks)
  • includes/calendars/views/default-calendar-list.php (1 hunks)
  • package.json (1 hunks)
  • readme.txt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • readme.txt
🔇 Additional comments (2)
package.json (1)

5-5: Version bump aligns with security fix.

The version increment to 3.5.10 appropriately reflects the IDOR vulnerability fix being introduced.

includes/calendars/views/default-calendar-list.php (1)

139-156: The nonce is already available in the frontend. The simcal_common_scripts_variables() function at includes/functions/shared.php:166 creates and passes the nonce to the frontend via wp_create_nonce('simcal'), which is then localized as part of the script variables. The frontend JavaScript can access this nonce through the localized simcal_default_calendar object.

Likely an incorrect or invalid review comment.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants