This was necessary due to several security concerns, partly discovered by the team, partly by third-party security experts:

A bad request could be made to the WordPress site targeting a specific plugin, for example with a request method or parameters that said plugin does not expect. Following that, the plugin might throw an exception, causing the plugin to be paused – i.e. an attacker could intentionally use such requests to force pausing of a plugin. This was arguably the most severe concern, since, while plugins should absolutely validate parameters rather than causing a fatal error, many have weaknesses in this area.

A flaw in one plugin could cause another plugin to be paused, rather than the flawed plugin itself. A good example of this is exceeding the memory limit: plugin 1 runs a way too expensive procedure, but then the memory limit is reached by a random plugin 2, causing the latter to be the origin of the fatal error.

A plugin failure in the frontend could affect that plugin to be paused in the backend, although it might not have caused a fatal error there. The frontend is a “non-protected endpoint”, for which plugins or themes should never be paused.

Multiple follow-up tickets were created to mitigate these issues, but eventually the team came to the conclusion that all these tweaks would have only slightly reduced the attack vector, rather than eliminating it.

A completely new approach was required, which would require additional time to be planned and implemented.

This post outlines the new proposed approach in detail. Please share it and request feedback, both from community members and people less active in the WordPress ecosystem – particularly security experts and hosting engineers. We would like to ensure that the approach is solid to proceed with before it is fully implemented.

Goal of the Fatal Error Protection

The primary goal of the feature remains the same as it was originally:

It should be possible for an administrator to access their admin backend, even in case of a fatal error.

While this does not reduce the risk factor of a PHP or extension update, it encourages users to perform an update despite the risks, as they will still be able to at least temporarily fix the problem.

If an update breaks their site, it will currently cause a so-called “white screen of death”. With the fatal error protection, it should display a specific screen informing the user about that there is a technical problem with the site. The administrator should then be able to access their backend. There they can look at the extensions that are broken and either deactivate them to fix the problem, or find out about the error and forward it to a developer of their choice. Even in the latter case, the administrator might see enough value in deactivating the broken extensions to at least temporarily ensure the site’s frontend is accessible again.

A secondary goal of the feature is to inform the site owner about fatal errors that have occurred for visitors of their site, without the owner being involved. This ensures that in case an administrator forgets to check their site after an update or if an error has happened in a rather specific area, they still find out when their site is inaccessible.

Explicitly not a goal of the fatal error protection is error logging. While it should be possible for an administrator to see the latest error which an extension has caused and which has resulted in that extension’s pausing, not more errors than necessary as that should be stored in the database. Error-logging is a different feature focused more towards developer audiences, and an implementation using the WordPress database could easily clutter that and decrease performance of a site, thus introduce negative side effects for minor benefits. It should also be noted that the fatal error protection is not related to recovering a hacked site.

As the feature is targeted towards rather non-technical administrators that do not have capabilities to access or modify their site’s codebase, it should be opt-out via code mechanisms such as constants or filters, so that more advanced developers can disable the feature if they prefer.

The feature is targeted for WordPress 5.2 and will be in support of bumping the minimum required PHP version of WordPress to 5.6, which will happen as part of that release as well.

Introducing a Recovery Mode

What we recognized is that the idea of pausing extensions (plugins and themes) globally is the problem. If an attacker can force-pause extensions, essentially causing them to be deactivated on protected endpoints such as the admin backend or the login page, it can have severe impact for example on security. A security plugin might have a random weakness that, while being an indicator of a lack in quality, is not necessarily security-relevant. However, if that plugin also added two-factor-authentication to the WordPress login page, using the security-irrelevant flaw to pause the plugin would allow the attacker to bypass two-factor-authentication on the site.

The idea of pausing extensions makes sense, as it is impossible to act more granularly on a fatal error due to the lack of sandboxing in WordPress. However, it needs to be ensured that pausing happens only for certain users that have sufficient capabilities to fix the issues, either by permanently deactivating the flawed extension or contacting a developer to take care of it – typically the site owner, which in the case of WordPress is arguably an administrator user.

The new approach relies on the concept of a recovery mode. Only specific users should be able to enter recovery mode, and only in recovery mode extensions should be eligible for being paused. This ensures that a fatal error does not have global impact. If an attacker intentionally triggered a fatal error in a plugin, they would not get any more from that than they would at the moment.

The Intended User Flow

A fatal error occurs, causing the user to see a screen saying that the site is experiencing technical difficulties.

At the same time, a notification email is sent to the admin email address, informing about the fatal error, including the error details and a link with a secret nonce to enter recovery mode. This process is rate-limited, so a maximum of 1 notification email will be sent per hour (filterable).

If the user does not have access to the admin email address, the process stops here – they should not be able to enter recovery mode then.

The user accesses their emails and clicks on the included recovery mode link.

The WordPress site verifies that the nonce in the link is correct, sets a cookie containing another secret key on the user’s machine, and redirects them to the login page. At this stage, the user (or more specifically the client) has effectively entered recovery mode. On every subsequent request, the cookie will be verified by checking the secret key.

The user can now regularly login. If a fatal error occurs on the site, the extension causing it will be paused for the user, followed by a redirect to the same URL, until no longer a fatal error occurs.

The user can now reliably browse the admin backend. In the dashboard, they will see a notice informing about which extensions are currently paused for them. On the Plugins / Themes screen, they can either resume these extensions (if they think the problem has been fixed) or completely deactivate them (with that action affecting the site globally, as usual).

If the user wants to exit recovery mode, there is a link in the admin bar that lets them do so. Once the user clicks that, the cookie will be deleted and extensions will no longer be paused for them.

No user is browsing the site.

A fatal error occurs (for example in a Cron request), causing the same screen to be internally rendered (even though technically nobody will see it).

At the same time, the notification email mentioned above is sent (if not over the rate limit), to inform the person associated with the admin email (typically referred to as the “site owner”) for the website about the error.

Further Considerations

There are a number of additional considerations for the feature, other than the user flow:

The feature should only support pausing of extensions that are user-controllable, as in that access is not necessary to set them up. It therefore excludes support for drop-ins and must-use plugins.

At least in the first iteration of the feature, it should also not support multisite and the pausing of network plugins. While these plugins can technically be altered without access to the codebase, setting up multisite requires access to the codebase and is an advanced and, relatively seen, rare use-case. Adding support for multisite and network plugins would require much additional exploration and work regarding UI (e.g. should only network administrators or also site administrators be able to access the backend and resume those plugins?). Furthermore there are technical quirks that would need to be figured out in addition (cookie constants, which are needed for the new approach, are only available after network plugins have been loaded). While the feature could generally be supported in multisite even without supporting network plugins, it was decided to explicitly disable the fatal error handler and recovery mechanism for multisite in the first iteration, to explore a solid approach in the future.

It is impossible to pause WordPress core, which should not be an issue as core defines which PHP versions it supports and should be compatible with all of them. Even more than today though, it is important to ensure that full compatibility with the latest PHP versions is maintained.

The feature cannot function properly if a connection to the database or object cache (if used) cannot be established. The implementation will account for these cases so that it does not trigger PHP notices or exceptions, but it is impossible to work around these limitations further.

The mechanisms which relate to initiating the recovery mode must all be error proof and therefore executed early, before extensions which might cause breakage are loaded. This technically means execution must happen after the call to register_theme_directory() in wp-settings.php. These mechanisms are:

Verifying a request made from a recovery link, setting the recovery mode cookie and redirecting the user.

Verifying the recovery mode cookie and based on that enabling recovery mode for the current request.

Future Iterations

While the previously outlined approach is targeted towards WordPress 5.2, there is room for future iterations that can be released in follow-up versions. Current ideas include:

Improving the flow of how an administrator can receive a recovery link, since, in several cases, the admin email address does not cover such users correctly. The fatal error screen could show a link to a new screen that looks similar to the password recovery screen. Here a user could enter their email address, and if they had sufficient permissions on the site, a recovery link would be sent to their email address. In other words, in addition to the link going out to the admin email address, administrators could request their own recovery link manually.

Adding support for multisite and network-active plugins. Due to both technical and UI complications and the rather small and usually more advanced amount of multisites, it was decided to omit this for the first version. Since network plugins are however still user-managed (contrary to drop-ins and must-use plugins), it would make sense to eventually support them as well. This would also require thinking about a solid flow to network-resume plugins and handle network-wide recovery mode and related user capabilities.

Supporting further customization. While the first version allows overriding the feature, in the future more granular adjustments might become possible. Most likely, this will happen naturally through developer requests that can then be evaluated.

Feedback Requested

We would like to get feedback on the proposal, to make sure to get the implementation right this time. In particular, security and UX require thorough reviews. Please share your thoughts, and also spread the word about this post with others you think would be interested. You can also track the implementation via #46130 and the accompanying pull-request.

You can give feedback by commenting on this post or in the #core-php channel on Slack. We also have weekly meetings on Monday, 16:00 UTC.

Performance Benchmark

The following benchmark compares performance for a particularly sizeable post (~ 36000 words, ~ 1000 blocks) over the last releases. Such a large post isn’t representative of the average editing experience, but is adequate for spotting variations in performance.

For the millions of sites already running WordPress 5.0, 85% are using PHP 5.6 or above. We’ve also recently observed that showing notifications to encourage users to upgrade their PHP version has been very effective. Yoast SEO experimented with this last year, and found that site owners upgraded their PHP version at twice the rate than before they were showed the notification.

In light of that, I’d like to propose that in April 2019, we bump the minimum PHP version requirement to be 5.6. Sites that choose to remain on 5.5 or below will still receive security updates and possibly bug fixes, but would not be able to upgrade to the latest major WordPress version until they upgraded to a supported version of PHP.

Similarly, I’d like to propose that in April 2019, we bump the minimum MySQL version requirement to be 5.5. 98.5% of WordPress 5.0 sites are using MySQL 5.5 and above.

Depending upon feedback and effectiveness, we can follow up by bumping the required PHP version to 7 as early as December 2019.

We are super excited and proud to announce the #core-privacy team’s V2 Roadmap, which was published last week.

We’ve worked through the roadmap for the past few months, focusing on building for general privacy enhancements rather than specific legal obligations.

We intend to enhance our existing tools (the Privacy Policy generator, export tool, and the erasure tool we built for the V1 GDPR phase) while also developing extended support for things like Embed Privacy Controls and WP-CLI support. We are, of course, keeping an eye on legal developments in the privacy sphere to learn what tools and enhancements we’ll need to build a little later on as the needs change.

Where possible, we’ll work to build out plugins first, in order to make development easier for features, and then offer them as a merge to Core.

Let us know what you think of our roadmap! Share your feedback in the #core-privacy Slack channel.

As a friendly reminder, we are always looking for new contributors to our great little team. You can find our open Trac tickets here. We have bug scrubs on Mondays at 1600 UTC and we meet for office hours on Wednesdays at 19:00 UTC.

This post summarizes the latest weekly Editor meeting, held in the #core-editor Slack channel, on Wednesday, March 13, 2019, 14:00 UTC.

Block Directory Proposal

@youknowriad shared the block directory proposal post and raised that the current block registration APIs do not allow for this kind of plugins, and therefore this would need to be be resolved before building the directory. It is proposed that a private API is created first for use only with core blocks to allow iterations.

Discussions are to continue on the above post and the relevant pull requests.

Code Owners Experimentation Feedback

A few weeks ago, a code owners flow has been introduced to the Gutenberg repository. This allows to automatically ping people to review pull requests based on their interests on a certain area of the codebase.

A Discussion took place on the goal for this and whether it was achieved.

@aduth raised that one of the goals is to raise awareness and to get more core contributors.

@nosolosw felt that sometimes too many pings were sent out, and as a new contributor couldn’t commit the required time to review the codebase.

@youknowriad feels that the new workflow is not useful for occasional contributors.

@mcsf feels that the file paths do not map to the topics that people are interested in.

The new workflow will be kept for now, and reviewed at a later date.

Key Pull Requests

Block Management – @aduth is actively working on this PR, some minor decisions still to be made, including wording.

Section Block – General consensus is that this should be shipped as an experimental block first. This is hoped to land soon, and will be iterated upon.

Block outlines UI – The PR is close to merge, it improves the Block outlines for the hover and selected state. @kjellr would like some feedback and testing on this PR.

The last item on the list (which was in no particular order) was: “Forming a Triage team to tackle our 6,500+ open issues on Trac.”

“We need to do a lot of triaging work. There are over 6,500 open issues in our Core Trac right now. There have been some requests about moving to a different bug tracker and things like that. I would feel bad about doing that without cleaning up our home first.”

Matt Mullenweg – 2018 State of the Word.

As WordPress has grown, the volume of tickets in Trac has naturally increased. While the number of open tickets on its own should never be the sole metric of software health, a large number of open tickets can have many undesirable and frustrating consequences, such as tickets being lost or accidentally glossed over, and contributors not knowing where to focus their (often very limited) time and effort to have the largest impact.

This team will coordinate with component maintainers, release leads, project leadership, contributors, and other WordPress related projects with issue trackers outside of Trac (such as Gutenberg, new default themes, etc.) to ensure that everyone is empowered to focus on what they are best at: contributing!

With that in mind, let’s meet the new Triage Team!

Initial Team Structure

The following initial team structure was self-organized and was formed based on nominations and interestexpressed in the comments of Make WordPress Core posts related to this topic. The following people have a strong track record of contributing to WordPress, exhibiting good triaging practices, and being overall good community members. They also represent a range of disciplines to ensure every type of contribution is considered by the team when making recommendations for process changes.

This team structure can be altered at any time as needed and was created with the goal of getting the team to a point where it can be functioning and effective starting today. In addition, more team members are needed in order to accomplish these goals.

Jonathan has been a consistent contributor to the WordPress project since 2013, lending his time to various components and initiatives (such as Media, REST API, and Privacy), and has been a significant contributor to organizational tasks. He also helps run new contributor meetings where all questions about contributing are welcome. Having worked in such various capacities, he’s thrilled to be able to focus on the organization of the issue tracking tools and processes.

Chris has a long history of contributing to WordPress Core, particularly as part of ticket triage (including over 1,000 tickets triaged in the WordPress 4.4 and 4.5 release cycles). As a part of the team, Chris will be working to ensure that the triage team is meeting its milestone goals, performing ticket triages in an effective way, and working to improve and optimize processes.

Tammie has a background in ticket triage, especially as it pertains to designers and design UX/UI concerns. As Design Advocate, Tammie will be working to ensure the workflow needs and requirements of designers receive proper consideration and are represented in all decisions made by the team.

Sergey is a prolific WordPress contributor with a deep-rooted knowledge of Trac and the needs of developers contributing to the project. As Developer Advocate, Sergey will be working to ensure the workflow needs and requirements of developers receive proper consideration and are represented in all decisions made by the team.

Sheri has over 12 years experience supporting WordPress developers and users with an extensive background in triage and testing, most recently assisting with Gutenberg triage prior to its release in WordPress 5.0. She has a strong track record as a user and developer advocate and will ensure the team is communicating clearly (without jargon) to everyone to help build a strong, sustainable community of contributors.

Recent Challenges

Here is a list of some recent challenges that the team would like to explore solutions for:

Large time burdens on release leads to triage tickets in their release milestone.

Punting many issues each release, leading to frustration over poorly-set expectations.

Contributors don’t know where to spend time effectively especially when not contributing on a daily basis.

Tickets get buried, lost or glossed over.

Here are some metrics related to those problems:

The number of issues punted each release.

The number of interactions per contributor over time.

The number of stale and unactionable tickets left open.

Short Term Goals (First Half of 2019)

After reviewing current day to day Trac practices and considering both public and private feedback about the team, the immediate short-term goal of the team is to start a regular triage process to help maintain properly categorized and actionable tickets. Here are some of the ways that this can be done:

Create and execute a plan to work together with component maintainers and other contributors to triage open tickets with an emphasis on the Awaiting Review milestone and tickets that have become “stale”.

Provide any needed support to component maintainers in the form of (but not limited to): ticket scrubs, testing, ticket triaging.

Help release leads and deputies manage the flow of tickets into and out of release milestones.

Define and document WordPress ticket triage processes and best practices, including when to close an issue, requirements for moving an issue into a release milestone, etc.

Research and make some small process change recommendations (examples: new ticket resolutions, keywords, or workflows).

Sketch ticket flows for visual representations of processes.

What are the correct processes for supporting codebases in multiple locations (ie, Trac/SVN, GitHub, etc.).

Changes to Trac reports:

Which ones are no longer useful or manageable?

How do we better direct contributors to reports that require focus?

Where are there needs for new reports?

These are areas that require the focus and immediate attention of the team to ensure contributors are not overloaded and fully enabled to do their best work.

It’s important to note that none of the items above will replace the current responsibilities of component maintainers or ticket gardeners. Component maintainers and contributors are still encouraged to scrub tickets for their components in Trac. The Triage Team is not replacing that responsibility, but instead, are here to assist with that responsibility.

Component maintainers have a deep-rooted understanding of the component’s history, past decisions, and feature progression. They are the ones best suited to make decisions that will point the component in the direction they feel best aligns with the overall project goals and priorities. The Triage Team will work closely with component maintainers to expand the efforts around triage, help to improve those processes and ensure that tickets are actionable.

Long Term Goals (2019 and Beyond)

The ultimate goal of the team will be to make triage a scaleable, sustainable part of the WordPress project. Longer term, a roadmap will be established to detail the team’s vision. Here are a few potential long-term goals that have come up in discussions so far.

Automated workflow keywords. such as stale or needs-verification (to make sure the reported bug is still reproducible) for older tickets.

Documentation for onboarding new team members.

Creating a rotation where interested contributors can donate time to the team as part of fulfilling the 5 for the Future challenge.

Ensuring new tools and technologies in processes are properly supported (for example, NPM or Composer packages).

Creating a deprecation handbook with recommendations for how deprecated or removed parts of WordPress should be supported through tickets (What types of tickets are accepted or considered for how long under what circumstances?).

As changes to workflows are researched and evaluated, change recommendations will be published to the Make WordPress Core blog (and cross-posted where appropriate) for feedback.

Getting Involved

If you have an interest in being a part of this team and helping with its initiatives, please express your interest by commenting below. Feel free to be as specific as you’d like about how you would like to contribute to the team.

In the interest of full transparency, the following additional people have also reviewed this post and provided feedback about the structure and priorities detailed in this post: @chanthaboune, @helen, @joemcgill.