The effects of alcohol on sustanon 250 leucine for – real weight loss & bodybuilding benefits?
AI Assistant
[Bug/Feature Reques...
 
Notifications
Clear all

Bug [Solved] [Bug/Feature Request] Same-IP voting restriction in recent versions blocks logged-in users and breaks legitimate scenarios

7 Posts
2 Users
7 Reactions
167 Views
Posts: 35
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@doctorbr)
Trusted Member
Joined: 3 years ago
[#11611]
Description:

Hi wpDiscuz team,

I've identified a significant behavioral change introduced in newest wpDiscuz versions in the `voteOnComment()` method of `class.WpdiscuzHelperAjax.php` that causes the error "You are not allowed to vote for this comment (Voting from same IP)" to fire in cases where it shouldn't.

What changed:

In earlier versions the same-IP check in `voteOnComment()` was gated behind `!$isUserLoggedIn`
 
```php
// Only guests are checked by IP
if (!$isUserLoggedIn && md5($comment->comment_author_IP) == $userIdOrIp) {
    wp_send_json_error("wc_deny_voting_from_same_ip");
}
```
 

In v7.6.66, this condition was removed, and the check now applies to all users unconditionally, including logged-in administrators:
 

```php
// v7.6.66 — Everyone is checked by IP, regardless of login status
if ($comment->comment_author_IP == $userIP) {
    wp_send_json_error("wc_deny_voting_from_same_ip");
} elseif ($userID && $userID == $comment->user_id) {
    wp_send_json_error("wc_self_vote");
}
```
 

Two issues arise from this change:

1.Logged-in users should not be subject to IP-based restrictions. They are already uniquely identifiable by their `user_id`. The original logic correctly recognized this distinction. Two different registered users who happen to share the same public IP (e.g., coworkers on a corporate network) are two distinct, authenticated identities, blocking one from voting on the other's comment based solely on IP is incorrect.

2.The `elseif` structure prevents the correct error message from being displayed. When a logged-in user tries to vote on their own comment from the same IP, they receive the generic "Voting from same IP" message instead of the correct "You Cannot Vote On Your Comment" message. The IP check intercepts the request before the `user_id` self-vote check can run.

Real-world production scenarios affected:

  • CGNAT (Carrier-Grade NAT): Mobile carriers (4G/5G) share a single public IP among hundreds of subscribers. Two different registered users browsing via the same carrier could be blocked from voting on each other's comments.
  • Corporate/University networks: Employees or students behind a shared gateway IP cannot vote on each other's comments.
  • Misconfigured CDN/Proxy: If Cloudflare or another reverse proxy doesn't properly forward the visitor's real IP (e.g., missing `X-Forwarded-For` header), all visitors appear to have the proxy's IP.
  • Localhost development: All traffic originates from `127.0.0.1` or `::1`, making it impossible to test voting features locally.

Suggested fix: 

Restore the `!$isUserLoggedIn` guard that existed in earlier versions, so that the IP-based restriction only applies to guests, and change the `elseif` back to a separate `if` so that the self-vote check is always evaluated independently:
 

```php
$userIP = WpdiscuzHelper::getRealIPAddr();
$userID = get_current_user_id();

// IP-based restriction should only apply to guests
if (!$userID && $comment->comment_author_IP == $userIP) {
    wp_send_json_error("wc_deny_voting_from_same_ip");
}

// Self-vote check should always run independently for logged-in users
if ($userID && $userID == $comment->user_id) {
    wp_send_json_error("wc_self_vote");
}
```
 

This preserves the anti-abuse intent for guests while correctly relying on `user_id` for authenticated users.
 

Environment:
- wpDiscuz version: 7.6.66 (free)
- WordPress version: 7.0.4
- PHP version: 8.3.30
 

 

 
Disclosure: This bug report was drafted with the assistance of an AI coding assistant (Antigravity/Claude) based on my manual comparison of the wpDiscuz source code between versions. The analysis, code excerpts, and suggested fix were reviewed and approved by me before posting. All described behaviors were observed and reproduced in my local development environment (WampServer64 / WordPress 7.0.4 / PHP 8.3.30). 
 

 
Thank you for your time and for maintaining such a great plugin.
 
 

Topic Tags
6 Replies
Posts: 138
Support
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@hakob)
Estimable Member
Joined: 11 years ago

Hi @doctorbr , Thank you for the detailed report.

 
One correction that matters for you: this isn't a 7.6.66 change. It came in with v7.6.48, in a fix for a separate bug where guests were wrongly blocked from voting on guest comments — the login guard was dropped by accident while restructuring that check. Downgrading to 7.6.65 or 7.6.64 won't help; the code is identical there.
 
Your analysis is right on both counts, and the fixes will land in the upcoming release.

Reply
Posts: 138
Support
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@hakob)
Estimable Member
Joined: 11 years ago
 
wpDiscuz 7.6.67 is out, and both problems are fixed. Update from Dashboard → Plugins.
 
Signed-in users are now recognised by their account rather than their internet address, so colleagues in one office — or people on the same mobile network — can vote on each other's
comments again. And voting on your own comment now shows the right message instead of the confusing one about the same IP.
 
For anyone else finding this thread: this started in 7.6.48, not 7.6.66, so going back to an older version won't help.
 
Also fixed along the way: visitors whose internet address is hidden by a privacy plugin or proxy were all being treated as one person, so only the first of them could vote — they're
now asked to log in instead. Vote counts no longer disappear when someone isn't allowed to vote; only the buttons are hidden. And switching voting off now really switches it off.
Existing votes are untouched.
 
If your visitors share one connection (mobile networks, offices, universities), you can now let guests on the same address vote on each other's comments:
 
add_filter( "wpdiscuz_deny_vote_from_same_ip", "__return_false" );
 
Worth knowing first: guests are recognised by their internet address and nothing else, so everyone sharing it still counts as a single voter. They'd need to register to be counted
separately.
 
Thanks again for the careful report — it led us beyond the original problem.

Reply
Posts: 35
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@doctorbr)
Trusted Member
Joined: 3 years ago
Thank you for the fast and thorough fix in v7.6.67. 😀 

I've tested it and can confirm all the issues I reported are resolved:

  • Logged-in users sharing an IP can now vote on each other's comments ✓
  • Voting on my own comment correctly shows "You Cannot Vote On Your Comment" instead of the IP error ✓
  • The new `wpdiscuz_deny_vote_from_same_ip` filter is a great addition for sites with shared-IP visitors ✓

One small piece of UX feedback on the new `wpd-vote-readonly` behavior: the current implementation hides the vote buttons entirely (via `display: none !important`) when a user views their own comment or when a guest shares the comment author's IP.

While I understand the intent, completely hiding the buttons may confuse visitors. They won't know voting exists on the site and won't feel encouraged to register or log in. Many platforms (Reddit, Stack Overflow, YouTube) keep the vote buttons visible at all times and show an appropriate message or login prompt when an unauthorized click occurs. wpDiscuz already has this server-side logic in place (the AJAX handler returns the correct error and the front-end displays a toast).

Would you consider one of these alternatives for a future release?

  1. Keep the buttons visible but styled as "disabled" (e.g., reduced opacity, `cursor: not-allowed`, and a tooltip explaining why voting is unavailable).
  2. Add a setting/filter like `wpdiscuz_hide_readonly_vote_buttons` (default `true` for backward compatibility) so site owners can choose whether to hide or show them.

For now, I'm using the following CSS override in Additional CSS, which works well and has no side effects since the server-side validation still prevents unauthorized votes:

```CSS
#wpdcom .wpd-comment-footer .wpd-vote.wpd-vote-readonly .wpd-vote-up,
#wpdcom .wpd-comment-footer .wpd-vote.wpd-vote-readonly .wpd-vote-down {
    display: flex !important;
}
```

Thanks again for addressing the original bug so quickly. The restructured voting logic in v7.6.67 is clean and well-thought-out.

 

---

Disclosure: This reply was drafted with the assistance of an AI coding assistant (Antigravity v2.11.0/Claude Opus 4.6) based on my review and testing of the wpDiscuz v7.6.67 source code. The analysis was reviewed and approved by me before posting. All described behaviors were tested in my development environment (WampServer64 / WordPress 7.0.4 / PHP 8.3.30).
---

Reply
Posts: 138
Support
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@hakob)
Estimable Member
Joined: 11 years ago
@doctorbr , Thank you for testing so carefully and for writing this up. The UX point is well made, and we've adopted it for 7.6.68.
 
You offered us two options, and we've taken both — with one change to your proposal: the filter defaults to showing the buttons rather than hiding them. Your reasoning convinced us. Buttons that vanish leave visitors with no idea the site has voting at all, and since the server-side validation is what actually prevents unauthorized votes, showing them costs nothing.
 
What 7.6.68 does:
 
- Vote buttons stay visible for a visitor who cannot vote on a comment. The wrapper gets a new wpd-vote-disabled class, and the buttons render at reduced opacity with

cursor: not-allowed

- Hovering shows a tooltip with the reason — "You cannot vote for your comment" or "You are not allowed to vote for this comment". Both are the existing phrases, editable under wpDiscuz → Phrases → Errors, so they are already translated in every language pack.
- Clicking still reaches the AJAX handler and shows the same message as a toast. Nothing about the server-side checks changed.
- The new filter carries exactly the name you proposed. Returning true restores the 7.6.67 behavior:
  add_filter("wpdiscuz_hide_readonly_vote_buttons", "__return_true");
It also receives the comment and the reason voting was denied, so you can hide in one case and show in the other:
  add_filter("wpdiscuz_hide_readonly_vote_buttons", function ($hide, $comment, $cause) {
      // $cause is "self_vote" or "same_ip"
      return $cause === "self_vote";
  }, 10, 3);
One implementation note that may interest you, since you were working around this in CSS: we gave the visible state its own class rather than re-displaying .wpd-vote-readonly. The

display: none !important

 rule stays exactly where it is and now applies only when the filter opts into hiding, so the disabled styling has nothing to fight. Your override becomes unnecessary — you can drop it after updating — and wpd-vote-readonly still produces markup identical to 7.6.67 for anyone who prefers the buttons hidden.
 
Thanks again for the detailed reports, both this one and the original voting bug.

Reply
Posts: 35
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@doctorbr)
Trusted Member
Joined: 3 years ago
Thank you for implementing both suggestions in v7.6.68: the disabled state with reduced opacity and tooltip, plus the `wpdiscuz_hide_readonly_vote_buttons` filter, are exactly what I proposed. The implementation is clean and I've removed my CSS override from v7.6.67 since it's no longer needed. 👍 

However, I found an inconsistency between the tooltip and the toast message when a guest tries to vote while "Allow Guests to Vote for Comments" is disabled.

Steps to reproduce:

  1. Disable "Allow Guests to Vote for Comments" in wpDiscuz > Settings > Comment Thread Features.
  2. Open any post with comments in an incognito/private window (not logged in).
  3. Hover over a vote button on a comment that shares the visitor's IP (always the case in localhost, but also possible in production with CGNAT or corporate networks).
  4. The tooltip shows: "You are not allowed to vote for this comment (Voting from same IP)"
  5. Click the button.
  6. The toast shows: "Login To Vote"

Root cause:

The Walker (`class.WpdiscuzWalker.php`, line 305) determines the disabled state and tooltip for guests using only `shouldDenyGuestVoteFromSameIP()`. It never checks the `isGuestCanVote` setting. When guest voting is disabled AND the IPs match, the Walker concludes "same_ip" is the reason and sets the tooltip accordingly.

But the AJAX handler (`voteOnComment()`, lines 712–713) checks `isGuestCanVote` FIRST, before the IP check. Since guest voting is disabled, it returns `wc_login_to_vote` immediately, never reaching the IP check. The visitor sees two different explanations for the same denial.
 
There's also a related scenario in production: when guest voting is disabled but the visitor's IP does NOT match the comment author's IP (the normal case), `shouldDenyGuestVoteFromSameIP()` returns false, so the Walker renders the buttons as fully active, no disabled class, no tooltip. But clicking triggers the AJAX, which returns "Login To Vote" because guest voting is disabled. The visitor sees fully functional buttons that don't work.

I noticed that `$args["can_user_vote"]` is already computed correctly in `getCommentListArgs()` (`class.WpdiscuzCore.php`, line 2043) and passed to the Walker, but it's never read inside `WpdiscuzWalker::start_el()`.

Suggested fix: the Walker should check `$args["can_user_vote"]`(or the `isGuestCanVote` option directly) before falling through to the IP check. When a guest cannot vote because guest voting is disabled, the buttons should show the disabled state with the `wc_login_to_vote` phrase as the tooltip, matching what the AJAX handler will return on click.

Conceptually:
```
if ($currentUserID) {
      // logged-in: check self-vote by user_id (already correct)
  } else {
      if (!$args["can_user_vote"]) {
          // guest voting disabled → disabled state with "login" tooltip
      } else {
          // guest voting enabled → check same-IP (already correct)
      }
  }
  ```

Everything else in v7.6.68 looks correct and well-structured. The server-side vote checks, rate limiting, the new filter, and the disabled CSS are all solid.
 

```
Disclosure: This reply was drafted with the assistance of an AI coding assistant (Antigravity v2.12.2 / Claude Opus 4.6) based on my review and testing of the wpDiscuz v7.6.68 source code. The analysis was reviewed and approved by me before posting. All described behaviors were tested in my development environment (WampServer64 / WordPress 7.0.4 / PHP 8.3.30).
````
 

Reply
Posts: 138
Support
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@hakob)
Estimable Member
Joined: 11 years ago
@doctorbr , Thanks — your analysis is correct on both scenarios, and the fix is in for the next release (7.6.70).
 
You pinpointed it exactly: the Walker resolved the guest denial reason from shouldDenyGuestVoteFromSameIP() alone, while voteOnComment() rejects on isGuestCanVote before it ever reaches the IP check. So with guest voting disabled, a same-IP guest got the "same IP" tooltip and a "Login To Vote" toast, and a different-IP guest — the normal production case — got fully live buttons that answered the same way on click.
 
The Walker now resolves the cause in the order the AJAX handler checks it, and
$args["can_user_vote"] carries the first guest check, as you suggested:
if ($currentUserID) {
    $voteDenialCause = $currentUserID === (int)$comment->user_id ? "self_vote" : "";
} else if (!$canUserVote || trim($currentUserIP) === "") {
    $voteDenialCause = "login_required";
} else {
    $voteDenialCause = WpdiscuzHelper::shouldDenyGuestVoteFromSameIP($comment, $currentUserIP) ? "same_ip" : "";
}
Three notes on the details:
 
- One more case is folded into that middle branch: a guest whose IP resolves to
  empty is also answered with wc_login_to_vote by the handler (!$userID &&
  !$hasUserIP), so that now renders disabled with the same tooltip instead of
  live buttons.
 
- wpdiscuz_hide_readonly_vote_buttons gains "login_required" as a third $voteDenialCause value alongside "self_vote" and "same_ip", in case you switch on it.
 
- .wpd-vote-disabled deliberately sets only opacity and cursor, no pointer-events: none, and the click handler is untouched — so the buttons stay clickable and the toast still appears. That matters on touch devices, where the tooltip never fires and the tap is the only way to get the explanation.
 
Verified across all six combinations (guest / logged-in × guest voting on / off × same / different IP): tooltip and toast now agree in every one.
 
Thanks again for the precise report — the file and line references made it quick
to confirm, and it's good to hear the v7.6.68 changes worked out for you.

Reply