The Signpost

File:Windows Blue Screen on room full of computers.JPG
Grj23
CC0
277
100
800
Special report

What actually happened during the Wikimedia security incident?

screenshot of Meta-Wiki's recent changes feed showing many edits posting a strange message
Recent changes on Meta-Wiki show user accounts with advanced permission posting the message "Закрываем проект", which is Russian for "closing the project".
This security incident is also the subject of this issue's opinion essay, and covered in News and Notes.

It has become the talk of the town that somebody set up us the bomb, that we were on the way to destruction, that Wikipedia was hacked, and other such things.

Well, it kind of was.

A horrifying exploit took place, which could have had catastrophic and far-reaching consequences if used maliciously; instead, it seems to have happened by accident and was used for childish peepee-poopoo vandalism.

The official statement, which you can see here, does not say a whole lot about specifically what happened:


This is not very enlightening, so let's take a closer look.

The actual script, whose source code can be seen from the Phabricator ticket page, is relatively simple. It does not do anything particularly horrifying or complicated; mostly it's just dumb schoolkid vandalism. It cannot actually get into the backend database or the server's shell, which is where private data is stored, and irreversible actions can be taken: all it can do is make a big mess on the wiki.

The way it works hinges on the fact that, on MediaWiki, all users have a page called "common.js", which is where userscripts go. If you're logged in, yours is here; mine is here. On this page, you can put code that is automatically run whenever you load a page on the website. They can either be written in the file itself, or loaded from somewhere else.

In mine, for example, I have it (among other things) load User:JPxG/Difformatter.js, a script I wrote that gives me buttons in the editing box to automatically format external diff URLs (like my 123,456th edit, whose URL is https://en.wikipedia.org/w/index.php?title=&diff=prev&oldid=1336463538 and looks like this) into internal links (like Special:Diff/1336463538, which looks like this). Most userscripts do something along these lines. There are a great number of them, and there is a semi-active newsletter for new ones, which I at one point wrote an issue of.

There is also a page on every wiki called MediaWiki:Common.js, which the English Wikipedia has here, and Meta-Wiki has here. This is a version of the same page that runs for everybody on the entire site. Because this could be very easily used to make a huge mess, either intentionally or unintentionally, access to it is very limited: I am a template editor and an edit filter manager and one of the thousand or so sysops on Wikipedia who have to be elected, and I could put Goatse on the Main Page if I wanted to, but I still cannot edit the site's common.js unless I make a request for another userright, "interface administrator". There are only fifteen of these; in addition to being administrators, they are all serious-business technical editors like Izno and Oshwah who can be trusted around high voltage.

Anyway, here is what Ololoshka562's script does:

  • Loads jQuery, gets the account name of the current user, and checks to see if it has already infected the site. Literally, it fetches the current site's MediaWiki:Common.js and checks to see if it has "Ololoshka562" anywhere in it.
  • Tries to edit the sitewide common.js, and replaces it with a gigantic block of gibberish. This gibberish is also JavaScript, but it's encoded as a URL is, so it is kind of hard to read. The script de-gibberishifies it later, so the only reason it's that way is to make it hard to read the code. Presumably, if it was just written directly, it would be obvious what it did, so it is kind of munged up.
  • Also edits the current user's common.js, and replaces it with the same bolus. Only interface administrators can edit the sitewide common.js, so this allows it to work on people who aren't intadmins.
  • Tries to use Special:Nuke three times. If you aren't an administrator, you can't do anything from this page, but I can use it to delete massive numbers of pages. That is what this script does.
  • Gets twenty random pages and tries to vandalize them by adding what's now File:Woodpecker10.jpg (this file didn't exist when vandalism occured), and then tries to load... something... from some sleazy-looking website I've never heard of. This site was, by March 2026, not only nonexistent but also unregistered.
  • Gets twenty more random pages, and tries to delete them. If you aren't an administrator this won't do anything.

The actual bolus of crap that it loads does a few more annoying things:

  • Loads itself.
  • Makes every link to a page called "common.js" unviewable, so you cannot fix it from the normal web interface.
  • Redefines the importScript function so that, when userscripts try to load other userscripts, instead of the local site they load them from cyclowiki.org.

Strewn among this is a bunch of junk that doesn't do anything malicious, and looks like it came from some normal wiki's Common.js (like you would find here) to expand and collapse boxes, tables, and so on.

As far as I can tell, this was either made purely for the lulz, or as part of some puerile beef between two random wikis. It doesn't do anything permanent or extremely dangerous; basically everything it does is within the interface that MediaWiki exposes to users. It does load and execute random JavaScript; at the time it was written, whatever was in those offsite URLs could have been some kind of horrifying smallpox code that stole your banking details. However, it didn't do this when it was actually executed, because the URL didn't exist anymore. Whatever heist this was originally cooked up for, if it was carried out at all, seems to have been finished and wrapped up years ago. This script is basically just a random grenade that was left lying in a cornfield. It was basically harmless, except in the specific scenario where somebody with extremely powerful sitewide permissions decided to import and run it with full privileges, which is usually something that people do not do. Mostly because this kind of thing can happen as a result.

Essentially, to carry the analogy further, a grenade lying in a random cornfield is not a particularly dangerous or sophisticated attack against the nation in question. It would cause significant damage if a head of state picked it up off the ground and fixed to take a bite out of it, but under normal circumstances there are people whose job it is to prevent this from happening.

Why was it the case that this could happen?

In the aftermath of every accident, it is necessary to figure out not just why it happened, but why it was allowed to happen. The "find one guy to yell at" system is alluring, because it is simple, but in most cases it is not sufficient to explain failures. Especially with systems as complex as modern software, it is rarely the case that the person who bumped into the "blow everything up" button is to blame — for starters, why is there a "blow everything up" button in the first place? Was it right next to the light switch?

At the Meta-Wiki page created to discuss the incident, a great deal of confusion ensued. Generally speaking, in the software industry, this is not supposed to happen. Over decades, it has become pretty well understood that some activities are inherently risky, and in most systems there is a framework in place to test them out where it won't blow anything important up.

The basic principle is similar to how, when the army is making some new type of gigantic bomb, and they need to test something by actually blowing it up in real life instead of working it out on graph paper, they go to some sand dunes in the middle of nowhere, even though their offices are in the middle of a densely populated city. Most companies and organizations that develop software have similar arrangements. Indeed, the prevailing practice in most software-related industries is to maintain two copies of infrastructure, called "testing" and "production".

On Wikipedia, there is a single-page version of the Nevada Test and Training range, at the aptly-named Sandbox; there's a whole-website-sized version of it at test.wikipedia.org. The Wikimedia Foundation, which develops a lot of software, has a wide variety of testing environments, which are used for developing the MediaWiki software and testing various things. It's not immediately clear what test was being done here, or why it was being done on the live site, or why it was being done with an account with such high privileges (e.g. an interface administrator).

However, there are some clues. The most likely thing, in any situation like this, is that there wasn't a solidly established framework for whatever was being tested here; either it was a quick, one-off thing that nobody wanted to build a whole testing harness for, or it was something where a whole testing harness would be extremely time-consuming to create. This is not a very good reason to "test in production", as it's called, but it is often necessary on Wikimedia sites. This brings me to my next point.

MediaWiki doesn't really have version control or testing infrastructure

While MediaWiki may seem like a paragon of orderly version control — after all, every action a user account takes is logged, timestamped, diffable and reversible — in practice it has become kind of a mess.

As an example: on the English Wikipedia there are a great deal of templates and modules. The original purpose of the "template" function was to let the periodic table be displayed on every element's article without having to hard-code it in the article source; they now do basically everything. Templates (which use MediaWiki markup and HTML) and modules (which use Lua) do a dizzying variety of things, and handle virtually all elements of a Wikipedia page that aren't the bare text of articles, and sometimes that. They format infoboxes, display maps, organize maintenance, display citations, display a lack of citations, and most importantly provide functions and components for other templates.

Templates and modules all individually have version histories; for example, Special:History/Template:Section sizes. However, most templates on Wikipedia are meta-templates, which call other templates. For example, I created {{Generating stations in California}}, which is the big expandable box at the bottom of Topaz Solar Farm and Gateway Generating Station that lists all the power plants in the state. All of the categories and links are coded into that template. Navboxes are heavily used, so they are a very straightforward and simplified type of template. But even with this one, if you look at the tree of every template that the template itself uses, you get this:

Now, you might think 21 templates (what most programmers would call "dependencies") is not a whole lot for something as big as a navbox. But each of them have their own tree of dependencies. For example, here is every template used in {{Collapsible option}}:

Why does it matter what dependencies a template has? Who cares? Well, there's no form of inter-page version control whatsoever!

When you edit {{Generating stations in California}}, for example, you cannot specify that you want to use the version of {{collapsible option}} from 2026-03-09. The only option is to just use whatever the current version happens to be. This means that, from time to time, templates just break for no apparent reason, and the only way to debug or fix them is to go through everything they transclude individually and see what changed.

More relevantly to this incident, there is no way to "create a testing branch" of the whole dependency tree. If you want to make a version of {{Generating stations in California}} that has different colors, you cannot do this on your local machine, or even on a different Wikimedia site. You need to do it on the English Wikipedia specifically, because the English Wikipedia is the only MediaWiki install in the world that has this specific panoply of templates and modules and meta-templates. It's possible to create a separate copy of the template, on the English Wikipedia — most templates (especially complicated ones) have a sandbox subpage where you can test modifications. But there's no way to actually replicate the testing environment without replicating the entire English Wikipedia.

If templates were designed as a programming framework, there might be, but they weren't; they were designed as a way to put the periodic table at the bottom of articles about elements.

This may seem like it has nothing to do with userscripts, and I admit it is a long digression, but I mention it to illustrate a fundamental point about MediaWiki: it's a quarter-century-tall stack of weird kludges built on stuff that in most cases wasn't designed for its current purpose. Any time you are asking yourself why some weird thing happened, this is probably a big part of the answer.

What is to be done?

I may be biased in my characterization of the situation, but as far as I can tell, the root issue here is likely not that the Wikimedia Foundation employed engineers to poke around with the software, but rather that they did not employ enough engineers to poke around with the software.

The one thing that seems pretty clear is that this was not some kind of sophisticated cyberattack, and there was no Tom Clancy business — it was just a random grenade lying in a cornfield that was for some reason imported and run with one of the highest privilege levels possible. It did not have shell access, and it did not have database admin access, but it did have the ability to load random scripts for viewers of the site.

In all likelihood, whoever Ololoshka562 is had no clue that it was even happening, and certainly did not plant it there to make this incident happen on purpose. This is quite fortunate, because if they had, it could have been a giant global catastrophe. Wikipedia is one of the world's most widely-used websites, and it did not have an arbitrary code execution incident, but seemingly purely by coincidence. This is a pretty narrow bullet-dodge (or nuke-dodge as the case may be), and some changes need to be made.

What changes I cannot say. It's hard to say exactly what went wrong, and whether it was an infrastructure issue or an organizational issue or what — but it was very fucking bad, and it is of paramount importance that it never happen again.

+ Add a comment

Discuss this story

These comments are automatically transcluded from this article's talk page. To follow comments, add the page to your watchlist. If your comment has not appeared here, you can try purging the cache.
  • Odd to realize that the same software we all use every day on Wikipedia and let into our devices under the axiom that ‘of course it’s safe, it’s MediaWiki,’ can be ‘hacked’ so easily that a simple accident caused all of this. Better discovered by accident than through an intentional attack before we’re even aware that MediaWiki has this vulnerability, though, so in a way I think we’re lucky this happened before it was exploited by someone. Shadestar474 (they/he) (talk) 04:52, 10 March 2026 (UTC)[reply]
  • Yikes! Thank goodness this was handled quickly. As Shadestar474 states above, better to find out about this sooner than later. TheTechie[she/they] | talk? 04:55, 10 March 2026 (UTC)[reply]
  • There's a reason the top of our common.js pages says Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. There are plenty of editors making really useful scripts, but you just can't be running scripts if you don't know what they are. This goes doubly for administrators and infinitely more for people who have more serious privileges. With that said, this was obviously a mistake and in the end no harm was done. Thebiguglyalien (talk) 05:09, 10 March 2026 (UTC)[reply]
  • If the situation was resolved quickly, mainstream media would have covered the incident. Gladly, only Bleeping Computer covered the incident. Ahri Boy (talk) 05:51, 10 March 2026 (UTC)[reply]
  • The image of the Woodpeckers mating was not present at the time of the incident. The image did not exist on Commons. I saw the red link during the incident. The current image was added on March 9, 2026. Ellywa (talk) 06:49, 10 March 2026 (UTC)[reply]
    I was going to comment the same thing. Good thing it has been corrected now: "by adding what's now a photograph of two woodpeckers mating (this file didn't exist when vandalism occured)" Bennylin (talk) 10:20, 10 March 2026 (UTC)[reply]
  • FYI, More relevantly to this incident, there is no way to "create a testing branch" of the whole dependency tree. is not true. In many cases you can fairly easily use Special:Export to export the whole dependency tree, then on your testing wiki use Special:Import to import it. In some cases you may also need to track down code from MediaWiki:Common.js or MediaWiki:Common.css to copy, although TemplateStyles has made this less necessary in many cases. Anomie 07:01, 10 March 2026 (UTC)[reply]
  • Some notes about the script: Tries to edit the sitewide common.js, and replace it with a gigantic block of gibberish. This gibberish is also JavaScript, but it's encoded as a URL is, so it is kind of hard to read.The script de-gibberishifies it later, so the only reason it's that way is to make it hard to read the code. Presumably, if it was just written directly, it would be obvious what it did, so it is kind of munged up. - I think this is the incorrect conclusion to draw. This code needs to be url encoded due to the way it is working - its doing find and replace on things that have already been percent encoded. Best practise would probably be to write it encodeURIComponent( 'non-encoded code here' ) instead of directly encoding it for easier reading, but regardless the percent encoding appears to mostly have to do with the structure of the code. I don't believe it was an attempt at obfuscation. then add a tracking script to load... something... from some sleazy-looking website I've never heard of. This site was, by March 2026, not only nonexistent but also unregistered. - one thing to note here is it appears this was trying to exploit CVE-2016-6334 in order to load the other domain. This issue was discovered by me and User:Legoktm back in 2016. Even if the domain existed, it would not have worked on Wikimedia wikis after June 2016. It is interesting that it was used in the wild, so long after it was fixed. My primary guess here is that this script was originally intended for use in some sort of attacks against Cyclowiki in the distant past and perhaps that wiki was using an outdated version of MediaWiki at the time (Its currently is on 1.39.1 [Dec 2022], which is new enough by a wide margin to not to have this vulnerability but is old enough to have other publicly known vulnerabilities, so it seems like they aren't conscientious about applying security updates). If we want to cast our minds back to 2016, I guess its kind of noteworthy that this report was published in 2015 and sort of discusses the possibility of something like this. If an attacker was doing background research they could have seen it and been inspired by it. However the attack vector is also so obvious that that is probably just a coincidence. Bawolff (talk) 07:19, 10 March 2026 (UTC)[reply]
  • Really enjoyed this write-up. I look forward to asking questions and learning more about the WMF's plan to expand their engineering team to both prevent this incident from repeating and to improve the technical design and operation of the wikis. — ♠ Ixtal ( T / C ) Non nobis solum 07:48, 10 March 2026 (UTC)[reply]
  • @JPxG: The person who did this was "testing userjs loads" (i.e. loading as many random scripts as possible), per this edit history. This article goes out of its way to avoid naming and shaming anyone though, as it should, so I'm not sure how to put this bit of information in without violating that principle. Graham87 (talk) 09:00, 10 March 2026 (UTC)[reply]

















Wikipedia:Wikipedia Signpost/2026-03-10/Special_report