fix: enforce submission gate in AJAX submit_post (unauthenticated post via subscription-gated form) - #1928
Conversation
…orm) Frontend_Form_Ajax::submit_post() never called Form::is_submission_open(), so the mandatory-subscription / pack-ownership / post-limit gate enforced by the renderer was skipped. A logged-out visitor could scrape the site-wide guest wpuf_form_add nonce from any guest form and replay it against a subscription-gated form's ID, creating a post (published where the form publishes) with no order and no pending-payment status. Re-check the gate server-side for new posts before building the post array, mirroring the render path (same is_submission_open + wpuf_can_post filter). Edits (post_id present) are unaffected; guest and pay-per-post forms that legitimately allow submission still return 'yes'. Reported by Charles Vosburgh. Closes weDevsOfficial/wpuf-pro#1653.
|
Warning Review limit reached
Next review available in: 44 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe AJAX handler now revalidates submission access for new posts. It checks ChangesSubmission gate enforcement
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@includes/Ajax/Frontend_Form_Ajax.php`:
- Around line 185-196: Compute a single $is_new_submission predicate near the
start of the submission flow using both post_id absence and wpuf_form_status ===
'new'. Use this predicate for the is_submission_open/wpuf_can_post gate, all
other new-submission-only branches, and the $is_update assignment, removing the
duplicated later status extraction so draft-backed new submissions cannot bypass
validation.
- Around line 186-194: Update the AJAX rejection branch in the submission
handler around is_submission_open so the selected submission restriction message
is passed through wpuf_addpost_notice before choosing or returning the fallback
text, matching the notice-filter contract in Frontend_Form.php and keeping
customized messages consistent between renderer and AJAX responses.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e392bb30-87fa-4674-9aab-7dee26c4dd3b
📒 Files selected for processing (1)
includes/Ajax/Frontend_Form_Ajax.php
Address review: a submission with a post_id but wpuf_form_status 'new' is treated as a new post by the update logic, so it must go through the same subscription gate — key the check on both signals. Also run the rejection message through wpuf_addpost_notice so AJAX and the renderer surface the same customized notice.
Vulnerability
[WPScan] Unauthenticated post creation through a subscription-gated form (CVSS 5.3).
Frontend_Form_Ajax::submit_post()never calledForm::is_submission_open(), so the mandatory-subscription / pack-ownership / post-count gate that the renderer enforces (includes/Frontend/Frontend_Form.php) was skipped on the write path. It verified only thewpuf_form_addnonce, which for logged-out visitors is a site-wide constant — an attacker could scrape it from any guest form and replay it against a subscription-gated form's ID:Fix (minimal, mirrors the render path)
Re-check the gate server-side for new posts before building the post array, using the same call the renderer uses:
Non-breaking
yes(unchanged).post_idunset); edits are untouched.wpuf_can_postfilter is preserved, so Pro/extension grants still apply.Verified — before / after (local WP, real guest HTTP requests, no cookies)
Gated form =
post_permission=guest_post+payment_options=on+choose_payment_option=force_pack_purchase+post_status=publish. Guestwpuf_form_addnonce scraped/minted for user 0.Submit to the gated form:
{"success":true,…"message":"Post saved"}— post published, no order{"success":false,…"error":"You need to purchase a subscription package to post in this form"}— no post createdLegit non-gated guest form, on the patched code:
{"success":true,…"message":"Post saved"}— post created. Legitimate guest posting is unaffected.Note on nonce binding
The report also suggests binding the nonce to the form ID. That changes the shared guest nonce contract (JS + guest-page caching) and risks breaking legitimate guest submissions, so it's intentionally out of scope here — the server-side gate closes the reported bypass on its own. Can follow up separately if desired.
Reported by external security researcher Charles Vosburgh — please credit in the changelog/advisory.
Closes weDevsOfficial/wpuf-pro#1653.