Page MenuHomePhabricator

Security review for Extension:WP25EasterEggs
Closed, ResolvedPublic

Description

NOTE: Due to the time-sensitive nature of the Wikipedia 25 birthday celebrations, it is unreasonable to expect a full security review for this extension before a production deployment in January/February 2026. The developer @ATitkov will provide a self-review to the best of their abilities and @Jdrewniak will assume the security risk for deploying this to production. The self-review is tracked in T411130.

Project Information

Description of the tool/project:
The Wikipedia 25 Easter eggs extension will provide readers of Wikipedia with a celebratory mascot who will accompany them on their Wikipedia journey.

Description of how the tool will be used at WMF:
This extension is meant to celebrate Wikipedia's 25th birthday by enabling users to show an graphical mascot on the sidebar of Wikipedia articles on the Vector 2022 and MinervaNeue skins. This mascot may occasional be animated during parts of the users reading journey. Since the purpose of the extension is to celebrate Wikipedia's 25th birthday, it is by nature time-limited and temporary. There currently no intention of leaving this extension in production for longer than an a year after it has been deployed.

Dependencies
No external dependencies.

Has this project been reviewed before?
No, but we will undertake a detailed self-review as part of T411130.

Working test environment
Local setup available on documentation page:
https://www.mediawiki.org/wiki/Extension:WP25EasterEggs

Post-deployment
Primary developer is @ATitkov, manager is @cmadeo with support from the Reader Experience Team

Event Timeline

https://www.mediawiki.org/wiki/Writing_an_extension_for_deployment lists several steps which have not been resolved yet before requesting a Security review.

Jdrewniak renamed this task from [DRAFT]: Security review for Extension:WP25EasterEggs to Security review for Extension:WP25EasterEggs.Nov 26 2025, 9:14 PM
Jdrewniak updated the task description. (Show Details)
sbassett changed the task status from Open to In Progress.Jan 5 2026, 5:46 PM
sbassett assigned this task to mmartorana.
sbassett triaged this task as Medium priority.
sbassett moved this task from Upcoming Quarter Planning Queue to In Progress on the secscrum board.
sbassett moved this task from Incoming to In Progress on the Security-Team board.

Hi @Jdrewniak - to help us scope this review, could you clarify the expected deployment window more precisely ?

Also, do you anticipate a staged rollout or a single deployment, and is there a planned removal date given this extension is temporary ?

hi @mmartorana sorry I missed that previous message. To answer your questions, the deployment timeline for this extension is to deploy it to production by the week of February 15th. We hope to have it enabled on beta cluster next week. This extension will be deployed globally, but it will be gated by community configuration settings, which will disable the feature from appearing on wikis that don't reach community consensus.

In regards to the removal date, this has been communicated as March 16th, so it'll only run for one month! (although I wouldn't mind keeping it on for longer).

This feature will remain supported until 16 March 2026, after this we will remove the feature from all Wikis.

Since our planned rollout date is in about 12 days, wondering whether there's any additional questions or concerns from Security side, @mmartorana

Thank you so much!!

Thanks for the ping! We’re aware of the rollout timeline.

We’re pairing on the review with @ASanford-WMF to move this along.

I’ll follow up shortly if any security concerns or questions come up; otherwise we’ll confirm once the review is complete.

Hi @mmartorana and @ASanford-WMF ,
Thank you both for your work on this review, as you can both see, the volume of code in this repo has increase substantially since we requested this review in January, so I can only imagine the effort required to undertake this. Unfortunately, we are working towards a hard deadline of Monday Feb 16th for this project, which will mean we will have to deploy this into production on that day. The reason that this is a hard deadline is because there has been press and media coordinated with this launch, spread out across many outlets, and rescheduling that press is not possible at this time. Because of that, we'll have to proceed with this launch even if the security review isn't finished yet. I've been given the guidance that security review shouldn't be a hard blocker for releases, so I'm working under that assumption (please correct me if that's not the case) but we are committed to fixing any issues that arise from the review ASAP, even if it means disabling the extension. Our contractor @ATitkov is ready and available to resolve any issues that crop up during this review.

I have approval from @NBaca-WMF to assume responsibility for proceeding with the following deployment plan, security-review notwithstanding:

  • Thursday Feb 12: Enable this extension in production today hidden under a feature flag -- essentially wfLoadExtension( 'WP25EasterEggs' ); for all Wikipedias. This will hopefully reveal any performance issues with the extension when it's in an idle state and gives us a chance to rollback tomorrow.
  • Mon Feb 16: Enable the $wgWp25EasterEggsEnable = true; flag for all wikipedias.

In the first week, this extension will opt-in only by individual users, but it will also have to be opt-in on a per-wiki basis by admins, through a communityConfig page. The extension can also be immediately disable through that communityConfig as well. The following wikis have expressed interest in enabling this feature on the project meta-page:

Czech: cs.wikipedia.org
French: fr.wikipedia.org
Gorontalo: gor.wikipedia.org
Italian: it.wikipedia.org
Indonesian: id.wikipedia.org
Madurese: mad.wikipedia.org
Thai: th.wikipedia.org
Vietnamese: vi.wikipedia.org
Wayuu: guc.wikipedia.org
Sicilian: scn.wikipedia.org/

This double opt-in "soft-launch" scenario is meant to de-risk this deploy as much as possible, so that hopefully by the week of Feb 23rd, we'll be able to show baby globe more broadly as more wikis opt-in. Please let me know if there are any immediate concerns or issues that have cropped up that might affect this plan. @mmartorana and @ASanford-WMF thank you both again for working on this. Looking forward to the outcome of the review.

Hi @Jdrewniak! Thanks for the heads up. That all sounds good on our end. We're aiming to have our review posted tomorrow 👍

Security Review Summary - T410091 - 2026-02-13
Last commit reviewed: 38ce7a2

Summary

Overall, the extension was not found to have issues of critical or high severity. Some medium severity XSS issues in the handling of translation strings were noted, and should be addressed. Some vulnerable or outdated packages were noted for completeness, but no reachable vulnerabilities were found. Finally, a note on unreachable code (incidentally containing vulnerabilities) is included below.

The overall risk rating is: medium.

Vulnerable Packages - Production
Risk: none

No npm or composer vulnerable packages are being used in production.

Vulnerable Packages - Development
Risk: none

VulnerabilityPackageNotesServiceRemediationRisk
Uncontrolled Recursion (CVE-2025-50537)eslintNot using custom rules or serialization module, vulnerable code is not reachable.snyk(none) Informational
Memory LeakinflightNot directly using this package within the extension.snyk(none) Informational
Prototype Pollution (CVE-2025-13465)lodashVulnerable functions _.unset and _.omit not being used.snyk(none) Informational

Outdated Packages
Risk: low
As reported via npm outdated: none

As reported via composer outdated:
(no explicit vulnerabilities reported, simply noting for completeness' sake.)

PackageCurrentLatest
doctrine/dbal3.10.44.4.1
doctrine/sql-formatter1.5.31.5.4
giorgiosironi/eris0.14.11.0.0
justinrainbow/json-schema5.3.16.6.4
lcobucci/jwt4.1.55.6.0
mediawiki/mediawiki-codesniffer48.0.050.0.0
mediawiki/mediawiki-phan-config0.18.00.19.0
mediawiki/minus-x1.1.32.0.1
monolog/monolog2.11.03.10.0
phpunit/phpunit9.6.3412.5.11
psr/http-message1.12.0
psr/log1.1.43.0.2
psr/simple-cache1.0.13.0.0
psy/psysh0.12.190.12.20
symfony/yaml6.4.307.4.1
wikimedia/parsoid0.23.0-a140.23.0-a15
lcobucci/clock2.2.03.5.0
mediawiki/phan-taint-check-plugin8.0.09.0.0
netresearch/jsonmapper4.5.05.0.0
phan/phan5.5.26.0.1
phpcsstandards/phpcsextra1.4.01.5.0
phpcsstandards/phpcsutils1.1.11.2.2
phpdocumentor/reflection-docblock5.6.66.0.1
phpdocumentor/type-resolver1.12.02.0.0
phpunit/php-code-coverage9.2.3212.5.3
phpunit/php-file-iterator3.0.66.0.1
phpunit/php-invoker3.1.16.0.0
phpunit/php-text-template2.0.45.0.0
phpunit/php-timer5.0.38.0.0
sabre/event5.1.76.0.1
sebastian/cli-parser1.0.24.2.0
sebastian/code-unit1.0.83.0.3
sebastian/code-unit-reverse-lookup2.0.34.0.1
sebastian/comparator4.0.107.1.4
sebastian/complexity2.0.35.0.0
sebastian/diff4.0.67.0.0
sebastian/environment5.1.58.0.3
sebastian/exporter4.0.87.0.2
sebastian/global-state5.0.88.0.2
sebastian/lines-of-code1.0.44.0.0
sebastian/object-enumerator4.0.47.0.0
sebastian/object-reflector2.0.45.0.0
sebastian/recursion-context4.0.67.0.1
sebastian/type3.2.16.0.3
sebastian/version3.0.26.0.0
squizlabs/php_codesniffer3.13.24.0.1
symfony/string7.3.87.4.4
theseer/tokenizer1.3.12.0.1

Static Analysis Findings
Risk: low

The following function is potentially dangerous if supplied with values affected by user input ("tainted" values). Currently, only one vulnerability exists related to this function (see General Security Issues below). However, vulnerabilities may arise in the future if code is added which passes tainted values the function.

  • domUtils.js - createElement: This function does not perform sanitization or validation of the value of tag or innerHTML parameters before using them to create an element within the DOM. Tainted input may lead to XSS vulnerabilities, for example by adding a <script> tag.

General code health score
Risk: low

  1. The Wikimedia code health check tool returned a weighted risk score of 29.50.
┌───────────────────────────┬────────────┐                 
│          Metric           │ Risk Score │                                                                                                         
├───────────────────────────┼────────────┤                                                                                                         
│ Vulnerable Packages       │ 0          │
├───────────────────────────┼────────────┤                                                                                                         
│ Package Management        │ 4          │
├───────────────────────────┼────────────┤
│ Test Coverage             │ 7          │
├───────────────────────────┼────────────┤
│ SAST                      │ 0          │
├───────────────────────────┼────────────┤
│ Non-automated Commits     │ 5          │
├───────────────────────────┼────────────┤
│ Unique Contributors       │ 10         │
├───────────────────────────┼────────────┤
│ Contributor Concentration │ 3          │
├───────────────────────────┼────────────┤
│ Language Guidelines       │ 7          │
├───────────────────────────┼────────────┤
│ Staff Support             │ 10         │
├───────────────────────────┼────────────┤
│ Task Backlog              │ 0          │
├───────────────────────────┼────────────┤
│ Code Stewardship          │ 0          │
├───────────────────────────┼────────────┤
│ Weighted Risk             │ 29.50      │
└───────────────────────────┴────────────┘

General Security Issues
Risk: medium

DOM-Based XSS in i18n messages

The following i18n messages are outputted to the page without proper escaping, leading to XSS in the case of a malicious translation.

  • communityconfiguration-wp25eastereggs-modeconfiguration-section-label
  • extension-wp25eastereggs-minerva-launch-banner-title
  • extension-wp25eastereggs-minerva-launch-banner-close-label
  • extension-wp25eastereggs-minerva-launch-banner-description
  • extension-wp25eastereggs-minerva-launch-banner-settings-label

For a proof-of-concept, set $wgUseXssLanguage = true; and visit http://YOUR_SITE/wiki/Special:CommunityConfiguration/WP25EasterEggs?uselang=x-xss. See the documentation for the x-xss language parameter.

A proof-of-concept cannot be provided for the remaining four cases as the code is unreachable (see section "Code Cleanliness Issues" below).

To remediate, the code outputting the messages into the HTML must properly escape the messages to defend against malicious translation strings. The use of mw.msg( ... ) and mw.message( ... ).text() is unsafe for potentially untrusted translation strings. Instead, mw.message( ... ).escaped() or mw.message( ... ).parse() should be used to ensure that the text is escaped or sanitized.

Alternatively, for the unreachable code containing XSS vulnerabilities, removing the code entirely would also remediate the issue.

The affected code is as follows:

  • resources/ext.wp25EasterEggs.config/config.js line 46.
  • resources/ext.wp25EasterEggs.minervaLaunchBanner/minervaLaunchBanner.js line 8.
  • resources/ext.wp25EasterEggs.minervaLaunchBanner/minervaLaunchBanner.js line 11.
  • resources/ext.wp25EasterEggs.minervaLaunchBanner/minervaLaunchBanner.js line 23.
  • resources/ext.wp25EasterEggs.minervaLaunchBanner/minervaLaunchBanner.js line 29.

Code Cleanliness Issues
Risk: low

Unreachable code in resources/ext.wp25EasterEggs.minervaLaunchBanner

The ext.wp25EasterEggs.minervaLaunchBanner resource module is defined in extension.json and is implemented in the resources/ext.wp25EasterEggs.minervaLaunchBanner. However, the module is never loaded, making the code unreachable. Also see "General Security Issues" section above for security vulnerabilities present within this module.

----

LOG

snyk

% snyk test --all-projects --dev

Testing /Users/alex/code/gerrit/mediawiki/extensions/WP25EasterEggs...

Tested 663 dependencies for known issues, found 3 issues, 5 vulnerable paths.


Issues with no direct upgrade or patch:
  ✗ Uncontrolled Recursion [Medium Severity][https://security.snyk.io/vuln/SNYK-JS-ESLINT-15102420] in eslint@8.57.0
    introduced by eslint-config-wikimedia@0.32.3 > eslint@8.57.0
  This issue was fixed in versions: 9.26.0
  ✗ Missing Release of Resource after Effective Lifetime [Medium Severity][https://security.snyk.io/vuln/SNYK-JS-INFLIGHT-6095116] in inflight@1.0.6
    introduced by @wikimedia/mw-node-qunit@7.2.0 > glob@7.2.0 > inflight@1.0.6 and 2 other path(s)
  No upgrade or patch available
  ✗ Prototype Pollution [Medium Severity][https://security.snyk.io/vuln/SNYK-JS-LODASH-15053838] in lodash@4.17.21
    introduced by eslint-config-wikimedia@0.32.3 > eslint-plugin-vue@9.33.0 > vue-eslint-parser@9.4.3 > lodash@4.17.21
  This issue was fixed in versions: 4.17.23



Organization:      asanford
Package manager:   npm
Target file:       package-lock.json
Project name:      WP25EasterEggs
Open source:       no
Project path:      /Users/alex/code/gerrit/mediawiki/extensions/WP25EasterEggs
Licenses:          enabled

composer outdated

% composer outdated
Color legend:
- patch or minor release available - update recommended
- major release available - update possible

Direct dependencies required in composer.json:
doctrine/dbal                      3.10.4     4.4.1      Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/sql-formatter             1.5.3      1.5.4      a PHP SQL highlighting library
giorgiosironi/eris                 0.14.1     1.0.0      PHP library for property-based testing. Integrates with PHPUnit.
justinrainbow/json-schema          5.3.1      6.6.4      A library to validate a json schema.
lcobucci/jwt                       4.1.5      5.6.0      A simple library to work with JSON Web Token and JSON Web Signature
mediawiki/mediawiki-codesniffer    48.0.0     50.0.0     MediaWiki CodeSniffer Standards
mediawiki/mediawiki-phan-config    0.18.0     0.19.0     Standard MediaWiki phan configuration
mediawiki/minus-x                  1.1.3      2.0.1      Removes executable bit from files that shouldn't be executable
monolog/monolog                    2.11.0     3.10.0     Sends your logs to files, sockets, inboxes, databases and various web services
phpunit/phpunit                    9.6.34     12.5.11    The PHP Unit Testing framework.
psr/http-message                   1.1        2.0        Common interface for HTTP messages
psr/log                            1.1.4      3.0.2      Common interface for logging libraries
psr/simple-cache                   1.0.1      3.0.0      Common interfaces for simple caching
psy/psysh                          0.12.19    0.12.20    An interactive shell for modern PHP.
symfony/yaml                       6.4.30     7.4.1      Loads and dumps YAML files
wikimedia/parsoid                  0.23.0-a14 0.23.0-a15 Parsoid, a bidirectional parser between wikitext and HTML5

Transitive dependencies not required in composer.json:
lcobucci/clock                     2.2.0      3.5.0      Yet another clock abstraction
mediawiki/phan-taint-check-plugin  8.0.0      9.0.0      A Phan plugin to do security checking
netresearch/jsonmapper             4.5.0      5.0.0      Map nested JSON structures onto PHP classes
phan/phan                          5.5.2      6.0.1      A static analyzer for PHP
phpcsstandards/phpcsextra          1.4.0      1.5.0      A collection of sniffs and standards for use with PHP_CodeSniffer.
phpcsstandards/phpcsutils          1.1.1      1.2.2      A suite of utility functions for use with PHP_CodeSniffer
phpdocumentor/reflection-docblock  5.6.6      6.0.1      With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.
phpdocumentor/type-resolver        1.12.0     2.0.0      A PSR-5 based resolver of Class names, Types and Structural Element Names
phpunit/php-code-coverage          9.2.32     12.5.3     Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator          3.0.6      6.0.1      FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker                3.1.1      6.0.0      Invoke callables with a timeout
phpunit/php-text-template          2.0.4      5.0.0      Simple template engine.
phpunit/php-timer                  5.0.3      8.0.0      Utility class for timing
sabre/event                        5.1.7      6.0.1      sabre/event is a library for lightweight event-based programming
sebastian/cli-parser               1.0.2      4.2.0      Library for parsing CLI options
sebastian/code-unit                1.0.8      3.0.3      Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup 2.0.3      4.0.1      Looks up which function or method a line of code belongs to
sebastian/comparator               4.0.10     7.1.4      Provides the functionality to compare PHP values for equality
sebastian/complexity               2.0.3      5.0.0      Library for calculating the complexity of PHP code units
sebastian/diff                     4.0.6      7.0.0      Diff implementation
sebastian/environment              5.1.5      8.0.3      Provides functionality to handle HHVM/PHP environments
sebastian/exporter                 4.0.8      7.0.2      Provides the functionality to export PHP variables for visualization
sebastian/global-state             5.0.8      8.0.2      Snapshotting of global state
sebastian/lines-of-code            1.0.4      4.0.0      Library for counting the lines of code in PHP source code
sebastian/object-enumerator        4.0.4      7.0.0      Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector         2.0.4      5.0.0      Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context        4.0.6      7.0.1      Provides functionality to recursively process PHP variables
sebastian/type                     3.2.1      6.0.3      Collection of value objects that represent the types of the PHP type system
sebastian/version                  3.0.2      6.0.0      Library that helps with managing the version number of Git-hosted PHP projects
squizlabs/php_codesniffer          3.13.2     4.0.1      PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.
symfony/string                     7.3.8      7.4.4      Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way
theseer/tokenizer                  1.3.1      2.0.1      A small library for converting tokenized PHP source code into XML and potentially other formats

Change #1239409 had a related patch set uploaded (by ATitkov; author: ATitkov):

[mediawiki/extensions/WP25EasterEggs@master] Escape the unescaped i18n messages

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

[...] leading to XSS in the case of a malicious translation

(and/or, IIUC, a malicious sysop editing the MediaWiki: messages on a local wiki; FWIW)

Change #1239409 merged by jenkins-bot:

[mediawiki/extensions/WP25EasterEggs@master] Escape the unescaped i18n messages

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

Change #1239419 had a related patch set uploaded (by Jdrewniak; author: ATitkov):

[mediawiki/extensions/WP25EasterEggs@wmf/1.46.0-wmf.15] Escape the unescaped i18n messages

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

Change #1239419 merged by jenkins-bot:

[mediawiki/extensions/WP25EasterEggs@wmf/1.46.0-wmf.15] Escape the unescaped i18n messages

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

Mentioned in SAL (#wikimedia-operations) [2026-02-16T08:52:24Z] <hashar@deploy2002> Started scap sync-world: Backport for [[gerrit:1239403|Add "Learn more" link below Baby Globe on Minerva (T417077)]], [[gerrit:1239404|Update Qids to initial public version]], [[gerrit:1239419|Escape the unescaped i18n messages (T410091)]], [[gerrit:1239418|Do not show companion when visual editor is active (T417078)]], [[gerrit:1239400|Setting $wgWp25EasterEggsEnable to true for Wikipedias. (T41711

Mentioned in SAL (#wikimedia-operations) [2026-02-16T09:16:19Z] <hashar@deploy2002> jdrewniak, jhsoby, hashar, stang: Backport for [[gerrit:1239403|Add "Learn more" link below Baby Globe on Minerva (T417077)]], [[gerrit:1239404|Update Qids to initial public version]], [[gerrit:1239419|Escape the unescaped i18n messages (T410091)]], [[gerrit:1239418|Do not show companion when visual editor is active (T417078)]], [[gerrit:1239400|Setting $wgWp25EasterEggsEnable to true for Wikipedias

Mentioned in SAL (#wikimedia-operations) [2026-02-16T09:35:17Z] <hashar@deploy2002> Finished scap sync-world: Backport for [[gerrit:1239403|Add "Learn more" link below Baby Globe on Minerva (T417077)]], [[gerrit:1239404|Update Qids to initial public version]], [[gerrit:1239419|Escape the unescaped i18n messages (T410091)]], [[gerrit:1239418|Do not show companion when visual editor is active (T417078)]], [[gerrit:1239400|Setting $wgWp25EasterEggsEnable to true for Wikipedias. (T4171

@ASanford-WMF thank you again for that detailed write-up. We patched the extension to remove the xss vulnerabilities as you advised and the patch has been deployed. The dead code you mention is related to a centralNotice banner that is included in this extension. That banner is dead code due to a last-minute decision not to run the centralNotice campaign for this feature, so it's a known issue, but one that will be resolved when we remove this feature next month.
Thanks again for all your hard work here! With the message parsing fixed, I'm signing off this task.

Change #1239978 had a related patch set uploaded (by SomeRandomDeveloper; author: SomeRandomDeveloper):

[mediawiki/extensions/WP25EasterEggs@master] Use mw.message instead of mw.msg to fix error

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

Change #1239978 merged by jenkins-bot:

[mediawiki/extensions/WP25EasterEggs@master] Use mw.message instead of mw.msg to fix error

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