From e04e87f9c8e7e4260636078c14be3721aecb3fd4 Mon Sep 17 00:00:00 2001
From: Sam Wilson <sam@samwilson.id.au>
Date: Fri, 9 Jan 2026 13:56:56 +0800
Subject: [PATCH] SECURITY: Remove custom CSS Index page field

Stop outputting unsanitized custom `<style>` on Page pages.

This doesn't remove the field from Index pages, that can be done
on individual wikis via config, so that they can still view any
content they have in this field.

Bug: T406088
Change-Id: Idd51e18479b32b7176b43ff74ca1c49d6bdd0628
---
 includes/Page/EditPagePage.php       |  6 ------
 includes/Page/PageDisplayHandler.php | 30 +---------------------------
 includes/Page/PageViewAction.php     |  6 ------
 3 files changed, 1 insertion(+), 41 deletions(-)

diff --git a/includes/Page/EditPagePage.php b/includes/Page/EditPagePage.php
index baddd5e0..8152b1f0 100644
--- a/includes/Page/EditPagePage.php
+++ b/includes/Page/EditPagePage.php
@@ -71,12 +71,6 @@ class EditPagePage extends EditPage {
 
 		$out = $this->context->getOutput();
 
-		// custom CSS for preview
-		$css = $this->pageDisplayHandler->getCustomCss( $this->getTitle() );
-		if ( $css !== '' ) {
-			$out->addInlineStyle( $css );
-		}
-
 		$inputAttributes = [];
 		if ( $this->readOnlyMode->isReadOnly() ) {
 			$inputAttributes['readonly'] = '';
diff --git a/includes/Page/PageDisplayHandler.php b/includes/Page/PageDisplayHandler.php
index 3d754c1a..06cf0096 100644
--- a/includes/Page/PageDisplayHandler.php
+++ b/includes/Page/PageDisplayHandler.php
@@ -70,30 +70,6 @@ class PageDisplayHandler {
 		return self::DEFAULT_IMAGE_WIDTH;
 	}
 
-	/**
-	 * Return custom CSS for the page
-	 * Is protected against XSS
-	 * @param Title $pageTitle
-	 * @return string
-	 */
-	public function getCustomCss( Title $pageTitle ) {
-		$indexTitle = $this->context->getIndexForPageLookup()->getIndexForPageTitle( $pageTitle );
-		if ( $indexTitle === null ) {
-			return '';
-		}
-		try {
-			$indexContent = $this->context->getIndexContentLookup()->getIndexContentForTitle( $indexTitle );
-			$css = $this->context->getCustomIndexFieldsParser()->parseCustomIndexField(
-				$indexContent, 'css'
-			);
-			return Sanitizer::escapeHtmlAllowEntities(
-				Sanitizer::checkCss( $css->getStringValue() )
-			);
-		} catch ( OutOfBoundsException ) {
-			return '';
-		}
-	}
-
 	/**
 	 * Santizes and serializes the raw index fields of the associated index page so
 	 * that they can be included inside mw.config in the Page namespace.
@@ -114,11 +90,7 @@ class PageDisplayHandler {
 		$serializedFields = [];
 		foreach ( $indexFields as $key => $val ) {
 			// fields may contain raw XSS payloads, santize before putting it in
-			if ( strtolower( $key ) === 'css' ) {
-				$serializedFields[$key] = htmlspecialchars( Sanitizer::checkCss( $val->getStringValue() ), ENT_QUOTES );
-			} else {
-				$serializedFields[$key] = htmlspecialchars( $val->getStringValue() );
-			}
+			$serializedFields[$key] = htmlspecialchars( $val->getStringValue() );
 		}
 		return $serializedFields;
 	}
diff --git a/includes/Page/PageViewAction.php b/includes/Page/PageViewAction.php
index 93741c5f..f0e88170 100644
--- a/includes/Page/PageViewAction.php
+++ b/includes/Page/PageViewAction.php
@@ -48,11 +48,5 @@ class PageViewAction extends ViewAction {
 		// add modules
 		$out->addModules( 'ext.proofreadpage.ve.pageTarget.init' );
 		$out->addModuleStyles( [ 'ext.proofreadpage.base', 'ext.proofreadpage.page' ] );
-
-		// custom CSS
-		$css = $pageDisplayHandler->getCustomCss( $title );
-		if ( $css !== '' ) {
-			$out->addInlineStyle( $css );
-		}
 	}
 }
-- 
2.43.0

