Page MenuHomePhabricator

Site JS reauth hack can be bypassed using 'centralauthtoken'
Open, MediumPublic

Description

Site JS reauth hack can be bypassed using 'centralauthtoken'. I realized this while writing this reply on the other task: T419621, T419621#11827741. 'centralauthtoken' auth can, in fact, be used from a browser that could be running malicious code, so this should not be allowed.

This assumes that you have WikimediaCustomizations and CentralAuth installed on your wiki.

API edits while not recently authenticated are supposed to be rejected. This behaves correctly (fails with userlogin-reauth error):

await (new mw.Api).edit('MediaWiki:Common.js', (revision) => revision.content + '// test');

This, however, succeeds in saving the edit, but it should fail with the same error:

mw.ForeignApi.prototype.checkForeignLogin = () => $.Deferred().reject(); // Make sure that the 'centralauthtoken' code path in CentralAuth is used
await (new mw.ForeignApi(mw.util.wikiScript('api'))).edit('MediaWiki:Common.js', (revision) => revision.content + '// test');

The fix for this would be to resolve T419353, and then make it so that CentralAuthTokenSessionProvider does not allow sensitive operations.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

Relatedly, we plan to do T206012, which in my view means that CentralAuthTokenSessionProvider should never allow editing site JS.

I thought this might be a side-effect of T207557: Don't count initial login as valid for any operation that requires reauth, i.e. that we might be counting the creation or use of catoken as "login time" and thus "too soon" for reauth.

Looking at the code, that doesn't seem to be the reason.

AuthManager.php
	securitySensitiveOperationStatus () {
		// ..
		if ( $session->canSetUser() ) {
			// ..
			$last = $session->get( 'AuthManager:lastAuthTimestamp' );
			if ( $id !== $aId || $last === null ) {
				$timeSinceLogin = PHP_INT_MAX; // Forever ago
			} else {
				$timeSinceLogin = max( 0, time() - $last );
			}
		} else {
			$timeSinceLogin = -1;

			$pass = $wgAllowSecuritySensitiveOperationIfCannotReauthenticate; // [ 'default' => true ]
			if ( isset( $pass[$operation] ) ) {
				$status = $pass[$operation] ? self::SEC_OK : self::SEC_FAIL;
			} elseif ( isset( $pass['default'] ) ) {
				$status = $pass['default'] ? self::SEC_OK : self::SEC_FAIL;
			} else {
				throw new \UnexpectedValueException(
					'$wgAllowSecuritySensitiveOperationIfCannotReauthenticate lacks a default'
				);
			}
		}

Where Session::canSetUser > Provider::canChangeUser > CentralAuthTokenSessionProvider::canChangeUser returns false.

And this flaw with $wgAllowSecuritySensitiveOperationIfCannotReauthenticate is indeed tracked at T419353 per @matmarex.

Relatedly, we plan to do T206012, which in my view means that CentralAuthTokenSessionProvider should never allow editing site JS.

That sounds like it may break some workflows… First thing that comes to mind is tools for syncing gadgets across wiki (I don't know if such a thing exists, but if it doesn't, it should). Personally I've also edited site CSS (not sure if I ever did it for JS) with mw.ForeignApi while cleaning up old junk as a volunteer global interface editor. Disallowing it only for CentralAuthTokenSessionProvider, and allowing e.g. OAuth over CORS, may be less problematic.

(Not saying that you mustn't do it, just that there might be some trade-offs)

Btw, if we find some workflows that we don't want to break, I also thought that we could allow cross-wiki editing with the reauth requirement (after T419353 is done) by "inheriting" the lastAuthTimestamp from the browser cookie session when creating the centralauthtoken.

sbassett changed the task status from Open to In Progress.Apr 21 2026, 4:46 PM
sbassett assigned this task to Catrope.
sbassett triaged this task as Medium priority.
sbassett moved this task from Incoming to In Progress on the Security-Team board.
sbassett changed Author Affiliation from N/A to WMF Product.
sbassett changed Risk Rating from N/A to Medium.
Mstyles moved this task from In Progress to Our Part Is Done on the Security-Team board.

Yes, I should have linked that to this task. Marking this as resolved.

matmarex changed the visibility from "Custom Policy" to "Public (No Login Required)".May 3 2026, 10:49 AM
matmarex changed the edit policy from "Custom Policy" to "All Users".

Change #1306011 had a related patch set uploaded (by Catrope; author: Catrope):

[mediawiki/core@master] Allow SessionProviders to disable security-sensitive operations

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

Change #1306012 had a related patch set uploaded (by Catrope; author: Catrope):

[mediawiki/extensions/CentralAuth@master] Disable all security-sensitive operations when centralauthtoken is used

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

Relatedly, we plan to do T206012, which in my view means that CentralAuthTokenSessionProvider should never allow editing site JS.

That sounds like it may break some workflows… First thing that comes to mind is tools for syncing gadgets across wiki […] with mw.ForeignApi while cleaning up old junk as a volunteer global interface editor. […]

https://www.mediawiki.org/wiki/Synchronizer does exactly this, which is how some popular gadgets stay in sync (example: https://www.wikidata.org/wiki/Q132165799), which has stopped working.

Now that we have better handling for reauthentication, and now that we've already made it global-ish on wiki farms (change 1285894), I think the correct solution here would be for centralauthtoken-based sessions to "inherit" the elevated login state from the session which generated the token.

sbassett removed a project: Patch-For-Review.
sbassett moved this task from Our Part Is Done to In Progress on the Security-Team board.
sbassett added a project: Patch-For-Review.
sbassett changed the subtype of this task from "Security Issue" to "Task".
sbassett updated Other Assignee, added: Catrope.