Page MenuHomePhabricator

Improve AbuseFilter handling of CreateLocalAccount autocreations
Open, Needs TriagePublic

Description

It has been a long-standing issue how we should handle forcible autocreations via Special:CreateLocalAccount in relation to AbuseFilter.
The main challenges are:

  • AbuseFilter cannot currently distinguish between normal autocreations and CreateLocalAccount autocreations.
  • For the latter type of autocreation, there is no way to reference the actual auto-creator using the user_ variables.
  • Because of this limitation, sysops using Special:CreateLocalAccount have to temporarily disable filters that would otherwise prevent CreateLocalAccount actions before performing them.

As far as I can tell, there are four possible approaches to this problem.

1. Compute user_ variables for CreateLocalAccount actions (see also T366858: AbuseFilter does not report user_group or user_name when CreateLocalAccount is performed)

This would allow filters to be written in a way like:

action === "autocreateaccount" &
!(user_rights contains "centralauth-createlocal") &
...
2. Separate CreateLocalAccount actions from autocreateaccount (see also T307828: Separate Special:CreateLocalAccount from autocreateaccount in abuse filters)

We could introduce a new action such as createlocalaccount.
However, this approach would likely require significant developer effort, as creating a new action is often not straightforward.
A conceptual concern is that no other actions would belong to this new type, since it is purpose-specific and essentially a “closed-set” action.

3. Allow AbuseFilter to ignore CreateLocalAccount actions

This could be reasonable because the centralauth-createlocal permission is restricted to sysops and stewards (by default).
However, another question arises: What if a project intentionally assigns this permission to a local user group?

For example:

  • nlwiki assigns centralauth-createlocal to vrt-agent.
  • zhwiki assigns centralauth-createlocal to event-organizer and ipblock-exempt-grantor.

Would it be acceptable for these local groups to unconditionally bypass AbuseFilter for forcible autocreations? If the answer is yes, then this approach becomes a viable option.

4. Add a "Bypass AbuseFilter" UI to Special:CreateLocalAccount

This would allow the performer to choose whether the autocreation should be evaluated by existing filters.
We could introduce a new user right, such as abusefilter-bypass-createlocal, and assign it to sysops and stewards to control who is allowed to use this flexibility.

Event Timeline

Restricted Application added subscribers: Stang, Aklapper. · View Herald Transcript

@Stang I would appreciate your input on the 3rd approach.

@DAlangi_WMF @matmarex I would appreciate your opinions on this matter, as you both often maintain AuthManager and CentralAuth. Thanks.

@DAlangi_WMF @matmarex I would appreciate your opinions on this matter, as you both often maintain AuthManager and CentralAuth. Thanks.

Personally, IMHO, I like options 2 and 4. Option 3 sounds tempting (maybe because it requires minimal effort to implement), but I'm not sure I can make a decision there, and it seems hacky.

The reason for those picks is that both reveal to the developer or performer (site administrator) or accounts with sufficiently elevated rights performing the action, that this is an entirely different flow from the normal account auto-creation. This means that the performer would have to make a judgment call, and at this point, they'll be aware of what they're doing. I would suggest that if this is to be implemented, the performer should be aware in some way that this action is about to be performed "forcefully".

A quick read of https://www.mediawiki.org/wiki/Help:Extension:CentralAuth/CreateLocalAccount says that this special page is used when a local account auto-creation failed for some reason, but I'm not entirely sure whether it reveals why the auto-creation failed in the first place (haven't tried). It would be nice if, upon forcing the creation, the site admin knows that the action is about to bypass some rules in place, in this case, an AbuseFilter rule.

To add, I'd be nice to also get some input from AbuseFilter folks if they think this is the right way to go, since this touches their domain. Thanks!

I don't think there's an easy way to handle a bypass option in the UI. You can bypass all permission checks with UltimateAuthority, but not permission checks from specific compontents. Letting power users unconditionally bypass checks with a permission similar to abusefilter-bypass-blocked-external-domains / sboverride / sfsblock-bypass / etc would be easy though.

The other options don't look great, except the first which should probably be done anyway (AIUI it's just a bugfix, there's no good reason no to set the user) but forcing filter maintainers to add exceptions for all filters via user_* variables doesn't seem ideal.

I don't think there's an easy way to handle a bypass option in the UI.

I guess the special page could dynamically add some userright or similarly communicate with Abusefilter via temporary permissions/groups. That's a bit hacky but easy to do.

@DAlangi_WMF @Tgr Thank you both for your input. AFAICT, option 4 appears to be the most suitable overall, and I have no objections to pursuing that direction.

I don't think there's an easy way to handle a bypass option in the UI. You can bypass all permission checks with UltimateAuthority, but not permission checks from specific compontents.

If we take the 4th approach, what do you think of injecting a URI query parameter to the request body and reading it in AbuseFilter? For instance:

AbuseFilterPreAuthenticationProvider.php
$bypass = RequestContext::getMain()->getRequest()->getPostValues()['bypassFilters'] ?? false;

This would be pretty hacky though.

Anyway, I now think option 1 needs to be implemented regardless. If the performer chooses not to bypass filters via the UI, it should probably be possible to reference them in AbuseFilter evaluation and logging:

  1. A sysop leaves the "Bypass abuse filters" unchecked on Special:CreateLocalAccount.
  2. Some filter fires for the forcible autocreation.

In this scenario, we would want the abuse log to reflect the actual performer of the action, rather than using a generic format, e.g.:

Account (talk | block) triggered filter 1, performing the action "autocreateaccount" on Special:UserLogin.

(where user_name is null), cf.:

Sysop (talk | block) triggered filter 1, performing the action "autocreateaccount" on Special:CreateLocalAccount.

(where user_name is Sysop).

That said, perhaps we should first merge https://gerrit.wikimedia.org/r/c/mediawiki/extensions/AbuseFilter/+/1194682 (if it looks good), and then revisit the UI-based bypass approach afterwards?

Change #1231049 had a related patch set uploaded (by Dragoniez; author: Dragoniez):

[mediawiki/extensions/AbuseFilter@master] Allow sysops to bypass abuse filters via Special:CreateLocalAccount

https://gerrit.wikimedia.org/r/1231049

Change #1247197 had a related patch set uploaded (by Dragoniez; author: Dragoniez):

[mediawiki/core@master] AuthManager: Pass $options to AuthenticationProviders during autocreation

https://gerrit.wikimedia.org/r/1247197

Change #1247198 had a related patch set uploaded (by Dragoniez; author: Dragoniez):

[mediawiki/extensions/CentralAuth@master] Pass extra form fields through to forced local account creation

https://gerrit.wikimedia.org/r/1247198