Runnable code examples are now live in the Code Reference

WordPress 7.1 shipped the first two runnable code examples in the Code Reference. They are powered by WordPress Playground, and more are coming in 7.2.

On the WP_HTML_Processor::class_list() Code Reference page, select Run button in the code snippet and the code example will run right there, in your browser.

Runnable snippets can be defined in the DocBlock of each method directly in the WordPress codebase. They use a slightly different syntax from the regular code examples:

<?php
/**
 * Generator for a foreach loop to step through each class name for the matched tag.
 *
 * ```php interactive
 * $p = new WP_HTML_Tag_Processor( "<div class='free &lt;egg&gt;\tlang-en'>" );
 * $p->next_tag();
 * foreach ( $p->class_list() as $class_name ) {
 *   echo "{$class_name} ";
 * }
 * // Outputs: "free <egg> lang-en "
 * ```
 */
public function class_list() {}

The part that makes it interactive is the ```php interactive language tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) on the code fence. A handbook page with all the details and instructions for authoring interactive code snippets will be published shortly.

Props to @jonsurrell, @dmsnell, @westonruter.

+make.wordpress.org/docs/

+make.wordpress.org/playground/

Replacing Dashicons in the admin bar and menu

A patch has been in progress since June that replaces Dashicons in the adminadmin (and super admin) bar and the sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. with WordPress icons, using the wp_get_icon() function that was introduced in WordPress 7.1. Props to @fushar, @wildworks, and @lucasmdo for moving this forward. Because the change being proposed is very visible, it deserves a wider audience than it has had so far.

Continue reading

WordCamp US 2026: PHP conversation

At WordCampWordCamp WordCamps are casual, locally-organized conferences covering everything related to WordPress. They're one of the places where the WordPress community comes together to teach one another what they’ve learned throughout the year and share the joy. Learn more. US 2026, a group of contributors gathered for an informal conversation about the relationship between the WordPress project and the PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher language and community. The discussion was held under the Chatham House Rule, so notes below are not attributed to individual participants.

Attendees: @jorbin @johnbillion @obenland @griffbrad @joemcgill @dmsnell @jason_the_adams @desrosj @mdawaffe @4thhubbard @westonruter @annezazu.

A framing question opened the conversation: what are our current pain points with the language, historically and today?

Pain points and concerns

Perception and Community Relations

  • Many in the PHP community don’t consider WordPress developers to be “PHP developers.” Part of this is due to WordPress being seen as dragging PHP backwards because of its backwards compatibility commitments.
  • Many PHP language features are discussed on the internals mailing list without a WordPress perspective in the room. This is something anyone can join but that we haven’t necessarily prioritized and causes missed opportunities. 
  • When folks raised a WASM proposal, there wasn’t interest at the time. It might be a more apt time to revisit this conversation.

Backwards compatibility and the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. ecosystem

WordPress’s long backwards compatibility window creates friction across the ecosystem:

  • Plugins that depend on other packages run into trouble because the broader PHP ecosystem doesn’t support versions as far back as WordPress does.
  • Possible responses discussed: contacting plugin authors directly, delisting incompatible plugins, and leaning on plugin developers to be more proactive. A complicating factor: most plugin authors aren’t keeping plugins up to date, and many don’t log in at all.
  • One forward-looking, wishlist idea that doesn’t solve backwards compat but that could potentially help with plugin security: PHP could add a language feature to load modules with flags applied, enabling a security policy for plugins. Any code required by untrusted code would itself be tainted as untrusted.

Testing and tooling

  • It can be hard to produce verifiable cases to test compatibility.
  • There’s an upcoming (not yet ready) release of PHP_CodeSniffer that fixes a lot of what we don’t currently have sniffssniff A module for PHP Code Sniffer that analyzes code for a specific problem. Multiple stiffs are combined to create a PHPCS standard. The term is named because it detects code smells, similar to how a dog would "sniff" out food. for. This would help extenders come up to standard quickly.
  • Code is landing in GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ that isn’t compatible with PHP 7.4. Differences between the automated tooling for Gutenberg versus CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. cause issues when that code flows into Core. 
  • A nightly PHP Docker container to run locally would help. WordPress could put in the work to do it. Early follow has started here.

PHP version adoption

PHP 7.4 is still running on roughly 18% of websites (stats). There’s been less of a compelling reason for sites to upgrade recently. Ideas discussed:

  • A coordinated push from hosts to get more sites upgraded.
  • Making PHP 8.x meaningfully faster for WordPress, so speed becomes the compelling reason to upgrade. 
  • Security is already a reason to push on to update since older PHP versions that WordPress supports are no longer receiving security patches. 
  • The issue is not that folks are on old versions of WordPress itself. Stats could be pulled to see whether that has changed.

WASM

The last time a WASM proposal was raised it failed to gather enough interest for people to advance it into an RFC.  At the same time, PHP receives lots of security issues, and reducing surface area could be helpful to them. WordPress is already using WASM client-side and with Playground. A more meaningful conversation with the PHP community about WASM would be worthwhile. Tied to this, it may be worth running a PHP extension with WASM, gathering operational data and experience, and sharing that back with the PHP internals to show real world use. 

Context for historical involvement

We discussed why more involvement hasn’t happened without any one structural issue to point to. The main venues are PHP Internals and PHP-FIG. WordPress discussed joining FIG roughly 12 years ago but decided it didn’t want to be involved and wouldn’t get any benefit.

There have long been backchannel relationships and occasional public collaboration, but nothing intentional. Some context on why involvement has been limited:

  • WordPress doesn’t need much from the language and has always been conservative in adopting language features. Server performance and security are what pull WordPress in; language features are pushed harder by frameworks like Laravel.
  • This kind of collaboration is a constant uphill battle: highly technical, intense work requiring focus, time, and persistence across many people, and even when it makes something better for WordPress, it may still take ten years for WordPress to be able to take advantage of them due to the long-tail support for older PHP versions.
  • There’s an inherent mindset shift between software developers and language developers (examples raised: translations, time/date handling).
  • There is a reported history of patches stalling upstream.

Language features, version gating, and polyfills

A provocation was shared for this discussion: Could WordPress start gating features by PHP version aka “if you want feature X, you must run PHP X”? . Generally, WordPress uses polyfills to fill gaps, and there was discussion of collaborating with PHP on early polyfills:

  • When PHP 7 features were polyfilled early in a dedicated file, WordPress could implement features on top of that APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. faster.
  • It was discussed that polyfilling new functionality could disincentivize people to update their PHP versions. It was discussed that this argument may not hold: that instead of doing what it claims, it only causes breakage for sites with older PHP veresions and the incentivization loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop is broken.
  • The absence of polyfills led to the creation of multiple incorrect implementations in Core. Having polyfils would be a way of giving proper tools to prevent ad-hoc, insecure, and incomplete implementations in WordPress.
  • WordPress requires only a small number of PHP extensions (currently just jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. and mysqlMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com). Per the data from sites phoning home, PCRE is present on 100% of WordPress sites and could be made required.
    • The required/suggested page is out of date in a few ways and needs updating.

Incentives for hosts to update

Attendees who work at or with hosts shared what would motivate PHP upgrades:

  • Higher asset utilization. “Run 40% more websites on the same RAM,” with fewer people needed to monitor server security.
  • Security and performance generally, framed as “save by updating.”
  • Data from Automattic’s servers could show noticeable differences between PHP versions. There used to be PHP benchmarking across versions; WordPress.comWordPress.com An online implementation of WordPress code that lets you immediately access a new WordPress environment to publish your content. WordPress.com is a private company owned by Automattic that hosts the largest multisite in the world. This is arguably the best place to start blogging if you have never touched WordPress before. https://wordpress.com/ is already on PHP 8.4.
  • New PHP features might enable new technologies, such as AI-focused capabilitiescapability capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability)..
  • MySQL has the same dynamic: new capabilities (vector search, for example) are being built while WordPress still supports very old versions.

Plugin developers

A release email could be sent to plugin developers when their plugins aren’t compatible with a PHP version.

Opportunities for overlap with PHP Core

  • Performance. There are Core PHP devs that have done substantial performance work in the text processing and other low-level functions space, and the last few PHP releases have all included heavy optimizations. WordPress sees benefits in the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. API but can’t take full advantage the way it could if that work were upstreamed. 
  • Upstreaming spec-compliant web standards into PHP: HTML parsing, URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org parsing, HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. parsing, Query arg parsing, MIME content-type inference. This is an area WordPress could help improve or sponsor work on, which would benefit WordPress and PHP at large.
  • WASM (see above).
  • Pushing hosts to update PHP (see above).
  • Do more to report back to the PHP internals and RFCs what our measured impacts are for different changes. Potential namespace resolution changes in PHP came up as an example as that would have real world impact on Gutenberg and new AI work (ex: the PHP AI Client).

Staffing around PHP compatibility

Staffing currently feels solid. Some history and risks:

  • There were rough patches, notably the PHP 8.0 update; 8.x releases have been more inclined to introduce breaking changes than past versions.
  • The bigger struggle is getting non-Core people (especially plugin developers) to be proactive about PHP compatibility.
  • WordPress makes local environments available to run tests against new PHP versions as soon as possible, and the “betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process.” support label for new PHP versions was dropped.
  • PHP 9 might be a bigger issue. If a major syntax change in PHP 9 makes it impossible to ship a WordPress release supporting both PHP 7.4 and 9, mitigations discussed: asking PHP to produce nightly builds (playground lets you run WordPress on upcoming PHP versions), running WordPress Docker images against PHP nightlies, and taking unit tests out of the Docker container for more flexibility.

Potential follow-ups

  • Have a more intentional conversation with the PHP community about WASM.
  • Pull WordPress version stats to check whether old-WP-version distribution has changed.
  • Explore benchmarking data to give hosts a compelling upgrade story and to do an upgrade push.
  • Explore upstreaming HTML API work into PHP/find ways to sponsor PHP core development on behalf of WordPress.
  • Explore compatibility emails to plugin developers.
  • Follow the PHP_CodeSniffer release that adds missing sniffs, and the namespace resolution discussion.

Props to @dmsnell and @zieladam for reviewing these notes.

#php, #php-compatibility, #summary, #wcus

Dev Chat summary: September 2, 2026

Start of the meeting in SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/, facilitated by @audrasjb 🔗 See the agenda post.

Announcements 📢

7.2

7.1.1

General

Discussion 💬

From @jeffpaul

Jeff resurfaced this heads up from @annezazu, for anyone who’s working on something for 7.2 to ensure they flag that to Anne for the roadmap post:

Howdy! I’m starting to work on a roadmap for WordPress 7.2 since we’re less than 2 months from betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 1. I wanted to check in to see what might be coming up across the project that folks are dedicated to working on. As a reminder, roadmaps aren’t meant to be completely comprehensive but are meant to reflect the priority work slated for the release. As a result, I won’t include every little detail and instead focus on getting the broad strokes in place. As always, I’ll share drafts as I go but just want to flush out anything early as I have a long list already!

@annezazu – link to the Slack thread

@audrasjb: “On my side, I’d say this feature (ticket #65910) may be a huge thing for support teams (on dotorg as well as for plugins/themes support teams if we make it an APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.). Design welcome but I think we can probably make a POC with the existing dashicons and basic styling.”

From @pbearne

Paul would love to see some of his patches that add tests get merged.

#7-1-1, #7-2, #core, #dev-chat

What’s new in Gutenberg 23.9? (2 September)

“What’s new in GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/…” posts (labeled with the #gutenberg-new tag) are posted following every Gutenberg release on a biweekly basis, showcasing new features included in each release. As a reminder, here’s an overview of different ways to keep up with Gutenberg and the Editor.

Image

What’s new in
Gutenberg 23.9?

Gutenberg 23.9 has been released and is available for download!

This version of Gutenberg brings some big quality-of-life editing improvements around blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. insertion and custom styling.

Stop searching for the inserter

Finding the inserter was challenging on some block selections. Now, you can insert from the block toolbar. Easily add a new block to a group or another image to your gallery without having to change selection or scroll to find the inserter. Be on the lookout for more improvements to the block inserter in upcoming releases.

Easily find custom style overrides

Global Styles now makes it easy to see which blocks have custom overrides applied to them. Rather than drilling through each block to find which ones have custom styles, a dot indicator is on each block with a custom style. If you want to see all of the customized blocks together, there’s an option to filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. only by blocks with custom styles.

Other Notable Highlights

  • Axial block gap for the group block. Flex and grid layouts can now have independent vertical and horizontal block gap spacing so you can dial in your design. (81476)
  • Style <label> elements from theme.json (81160)
  • Global Styles for more elements: Citations, Inputs, and Selects were all available in theme.json, but now you can use Global Styles to easily customize them. (80852)
  • Add custom Duotone colors to Global Styles. theme.json could provide duotone palettes, but you couldn’t add custom ones via Global Styles. Now, if you don’t like the theme’s provided duotones, add your own via the new Duotone tab in the Global Styles Colors section. (81605)

Changelog

Enhancements

Components

  • Adminadmin (and super admin) UIUI User interface: Add Navigation component and Page navigation slot. (79746)
  • Align legacy form control focus rings with WPDS. (80417)
  • Base Styles: Align input-control mixin to design system. (81357)
  • Base styles: Streamline focus ring override. (81242)
  • Calendar: Support custom root roles. (81443)
  • CollapsibleCard: Support multiple headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. descriptions. (81227)
  • DataViews: Pass the WordPress localeLocale A locale is a combination of language and regional dialect. Usually locales correspond to countries, as is the case with Portuguese (Portugal) and Portuguese (Brazil). Other examples of locales include Canadian English and U.S. English. to the date/datetime calendar controls. (81592)
  • Global Styles: Allow editing duotone palettes. (81605)
  • Menu: Add UI component. (79560)
  • RadioControl: Allow individual options to be disabled. (82026)
  • SearchableChipSelect: Add grouped items support. (80989)
  • SearchableChipSelectControl: Add form control to @wordpress/ui. (80980)
  • Theme: Add color warning diagnostics workbench. (81817)
  • UI: Accept locale codes in Calendar components. (81814)
  • UI: Add Spinner component. (81358)
  • UI: Add TextareaControl component. (81359)
  • UI: Add tooltips to Calendar and RangeCalendar navigation buttons. (81983)
  • UI: Align Calendar styling with WPDS tokens. (81438)
  • UI: Collapse item-popup item sizing to default and small. (81354)
  • UI: Expose keyboard shortcut presentation utilities. (81826)
  • UI: Set Calendar text direction automatically. (81982)
  • UI: Use the default neutral border for Cards (81746)

Block Library

  • Add transform to Row for Columns block. (81802)
  • Enable axial gap for Group and restrict to flex and grid layouts. (81476)
  • Global Styles: Register as label element. (81160)
  • List: Add Align Support. (68002)
  • More block: Clarify description about excerptExcerpt An excerpt is the description of the blog post or page that will by default show on the blog archive page, in search results (SERPs), and on social media. With an SEO plugin, the excerpt may also be in that plugin’s metabox. vs full content. (80619)
  • Playlist Track: Show upload spinner inline. (81445)
  • Playlist: Add bulk track metadata editing. (81441)
  • Query No Results: Add Border & Spacing Support. (64601)
  • Tabs: Make inactive panel content findable in page. (81743)

Post Editor

  • Command Palette: Add View post command. (66720)
  • Command Palette: Allow commands to override the categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. icon. (81787)
  • Editor: Defer hierarchical term filtering and soften announcements. (81422)
  • Editor: Migrate hierarchical term selector to @wordpress/ui. (81848)
  • Editor: Refactor ‘ErrorBoundary’ to use the new recommended components. (81638)
  • Editor: Simplify List View sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. shortcut handling. (81693)
  • Editor: Surface debugging details in the ErrorBoundary. (81642)
  • Editor: Use PluginSidebar in GlobalStylesSidebar. (81570)
  • Pre-publish panel: Remove the headings that repeat the panel title. (81806)

Block Editor

  • Add an inserter to the parent selector. (81532)
  • Global Styles: Expose additional elements in Typography and Colors. (80852)
  • Patterns explorer: Refactor the category sidebar to use Tabs. (81807)
  • Quick Inserter: Standardize the design of the Browse all button. (81827)
  • Writing flow: Select next block on Enter key. (63484)
  • Inbetween Inserter: Use average width of adjacent blocks for inserter size. (68074)

Dashboard

  • Dashboard Widgets: Let the host decide which component renders an action link. (81740)
  • Dashboard Widgets: Promote high-relevance actions into a chrome footer. (81556)
  • Dashboard Widgets: Resolve widgetWidget A WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. types without a metadata module. (81738)

Fields

  • Export the package stylesheet. (81769)

DataViews

  • DataViews: Add an aspect ratio toggle for grid layouts. (81604)

Collaboration

  • Add __unstable_wp_sync_storage filter for pluggable storage backends. (81697)

Site Editor

  • Update template section description. (81613)

Global Styles

  • Filter and indicate blocks that have custom styles. (81373)

Font Library

  • Add skeleton loader for the font preview images. (81047)

Bug Fixes

Components

  • InputControl: Hide the value-like placeholder Safari renders in empty date and time inputs in ui and components packages. (81991)
  • Admin UI: Fix the primary color of the Fresh admin color scheme. (81618)
  • BoxControl: Update the opposite side when ALT is held on the left or right input. (81530)
  • Button: Fix alignment in loading spinner for rtl screens. (81901)
  • DataForm: Fix the datetime control sending two updates per calendar interaction. (81440)
  • DataForm: Make the panel layout edit button the real field trigger. (80689)
  • DataViews: Fix date and datetime controls selecting the adjacent day. (81498)
  • DataViews: Fix invisible sticky Actions column divider. (82055)
  • DataViews: Sync the displayed calendar month with external value changes. (81635)
  • Duotone Picker: Stop the duotone bar offering to move its control points. (81850)
  • Fix Storybook accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) issues in stories. (81777)
  • Improve text detection for button icon-with-text. (81521)
  • InputControl: Vertically center date and time input values in Safari. (81361)
  • Menu: Close non-modal menus on iframeiframe iFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser. interaction. (81952)
  • Modal: Stop Escape key propagation on dismiss. (81785)
  • PaletteEdit: Expose palette swatches as command buttons. (82023)
  • Storybook: Handle production module load failures. (81867)
  • Theme: Improve color ramp contrast safeguards. (81185)
  • UI: Fix accessibility issues in form primitives and their stories. (81853)

Block Library

  • Accordion Heading: Route theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. spacing to the toggle button. (81976)
  • Dynamic Gallery block: Skip transforms that expect inner blocks, e.g. Image and Grid transforms. (82009)
  • Enable blockGap spacing supports in Query loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop block. (79689)
  • Fix MediaPlaceholder drag eligibility. (81431)
  • Fix playlist track toolbar insertion. (81639)
  • Fix: Accordion: Anchored hash inside the accordion throws the malformed URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org console error. (81780)
  • Fix: Skip empty block markup in navigation to prevent split UL elements. (78793)
  • Fix: Term Description block skips display filters inside Terms Query. (81290)
  • Icon: Fix margin being applied twice in the editor. (81292)
  • Inner Blocks: Fix bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. that caused alignment controls to show in Image blocks within a Gallery. (81606)
  • Pattern: Disable visibility support. (81866)
  • Playlist Track: Improve track upload error flows. (81878)
  • Post Template: Fix mover arrows and labels for blocks inside the grid view. (81120)
  • Preserve layout and style attributes on Column transform. (81855)
  • Rename the media editor toolbar button to ‘Edit image’. (81705)

Post Editor

  • Add context to change “revisionsRevisions The WordPress revisions system stores a record of each saved draft or published update. The revision system allows you to see what changes were made in each revision by dragging a slider (or using the Next/Previous buttons). The display indicates what has changed in each revision. code diff”. (81820)
  • Editor: Correctly mark ToolsMoreMenuGroup as a private SlotFill. (81503)
  • Editor: Fix start page/template modal footer overflowing the modal width. (82021)
  • Editor: Register the editor keyboard shortcuts from the provider. (81580)
  • Fix: Post Editor: 403 on /wp/v2/settings at boot for users without manage_options cap. (81813)
  • Fix: Post Editor: Canvas animates from the left when switching mobile/tablet preview to desktop. (81484)
  • List View: Make focus on mount opt in. (81659)
  • Notes: Keep the note actions menu in view for long display names. (81414)
  • Notes: Stop forcing capitalization of user names. (81788)

Block Editor

  • Block Editor: Don’t close inserter panel when inline quick inserter opens. (76241)
  • Border Panel: Fix incorrect panel label. (78830)
  • Dimensions: Fix aspect ratio and scale controls not reflecting external updates. (80747)
  • Fix parent inserter toolbar button alignment when text labels is enabled. (81608)
  • Fix viewport state values set by grid resizer. (81601)
  • Fix: Delete key on empty heading transforms following paragraph into heading. (78779)
  • Global Styles: Keep storing shadow presets as CSSCSS Cascading Style Sheets. variables when custom presets exist. (81346)
  • Hide layout panel when no controls are available. (81968)
  • RichText: Use the current record when handling Enter. (81696)

Global Styles

  • Close the revisions screen on the first back click. (81897)
  • Color Palette panel: Remove empty whitespace when there are no theme colors. (81894)
  • Fix: Responsive styles: When enabled and a font-size is set, the corresponding CSS variable remains undefined. (81854)
  • Group shadow editor rows as items. (81871)

URL

  • Clamp the truncated file name slice in filterURLForDisplay. (81529)
  • Fix: getQueryArgs discards everything after the second = in a query argument value. (81066)
  • Fix: URL: normalizePath drops the rest of the query after a second “?”. (81612)
  • Stop normalizePath throwing on a malformed percent sequence. (81086)

Data Layer

  • CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. Data: Stop storing NaN pagination totals for unpaginated endpoints. (82059)
  • Core Data: Validate the parsed-blocks cache against registered block types. (81809)

Env

  • Fall back to cached docker images when the registry is unreachable. (81631)
  • Update git to latest commit when --update passed. (81447)

Boot

  • Restore centered snackbar notices. (81995)

Element

  • Serialize memo-wrapped components instead of an empty string. (81986)

Collaboration

  • RTC: Disable collaboration for post types without custom fields. (81946)
  • RTC: Add fallback identities when user profiles are unavailable. (81408)
  • RTC: Fix hidden cursor in Details block. (81322)

wp-build

  • Build Package: Use Core’s boot module when a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. has none. (81761)

Font Library

  • Fix the preview weight for variable fonts. (81748)

Media

  • Fix clipped focus outlines in the media editor Details sidebar. (81703)

Site Editor

  • Use inverted ThemeProvider seed for portaled UI. (81653)

DOM

  • Treat a caret at a soft line wrap as an ambiguous position in Firefox. (81003)

Media Utils

  • Prevent white screen crash during undo operations when Media Modal is open. (79898)

Parsing

  • Fix: Line Break Tags Added to Scripts and Styles. (77542)

Paste

  • Fix: Stop stripping spaces inside inline HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. elements on paste. (76696)

Accessibility

Post Editor

  • Editor: Announce publish date changes to screen readers. (81629)
  • Make Back button grid column flexible. (81701)

Block Editor

  • Block Styles: Refactor the variation UI to use ui/Button. (81833)

Block Library

  • Playlist: Add aria-label to prevent placeholder as label. (81654)
  • Playlist: Update playlist track placeholder to match aria label. (81762)

Media

  • Media editor: Keep initial modal focus on the dialog frame. (81541)

Performance

Post Editor

  • Editor: Speed up the hierarchical term selector for large taxonomies. (81376)
  • Editor: Stop :has() selectors recalculating the whole document on every block selection. (81471)

Global Styles

  • Try caching gutenberg_get_global_styles. (81889)

Components

  • Theme: Avoid root-level relational selectors. (81457)

Experiments

Site Editor

  • Boot: Contain a surface failure to that surface. (81622)
  • Boot: Do not offer to edit a trashed entity. (81632)
  • Boot: Let the editor canvas navigate between entity records. (81590)
  • Boot: Mount the registered plugins. (81754)
  • Boot: Preview the site where the canvas has nothing to open. (81749)
  • Boot: Sync the editor’s device preview with the URL. (81617)
  • Boot: Translate the canvas click-to-edit label. (81620)
  • Boot: Warn before leaving with unsaved changes. (81625)
  • Edit Site Init: Seed the editor preferences the editor expects. (81628)
  • ExtensibleExtensible This is the ability to add additional functionality to the code. Plugins extend the WordPress core software. Site Editor: Add a theme preview page with global styles editing. (81954)
  • Extensible Site Editor: Add the Identity route. (81576)
  • Extensible Site Editor: Preview the site on Home for classic themes. (81578)
  • Extensible Site Editor: Show only the style book on Styles for classic themes. (81579)
  • Extensible Site Editor: Gate theme screens on theme support. (81581)
  • Lazy Editor: Keep the theme’s editor styles on the canvas. (81747)
  • Lazy Editor: Render the editor preferences modal. (81630)
  • Pattern List: Import a pattern from JSON. (81919)
  • Site editor v2: Fix block error with navigation-edit route. (82051)
  • Site editor v2: Fix template part list pagination and sorting. (82054)

Media

  • Media Editor Route: Override media edit links to point to the new experimental media editor. (81559)
  • Media Editor Route: Make the route look like it’s part of the media menu in the sidebar. (81565)
  • Media Editor Route: Try adding undo/redo and save/cancel actions to the header. (81563)

Post Editor

  • Editor: Offer the theme export from both site editors. (81992)
  • Editor: Set the width an entity opens at from the editor provider. (81750)

Dashboard

  • Quick draft: Replace Button+Link with LinkButton. (82031)
  • Dashboard: Add a Site Health detail page as the dashboard’s second route. (81729)

Documentation

  • Add Gutenberg version details for WordPress 7.1. (81600)
  • Adds JSdoc for audio block’s edit.js. (68865)
  • Adds JSdoc for avatar block’s edit.js. (68867)
  • Adds JSdoc for column and columns block’s edit.js. (68873)
  • Adds README for inspector-controls-tabs component. (69072)
  • BlockEditVisuallyButton: Update Developer Documentation. (68987)
  • Components: Update the combobox changes to be part of breaking change. (81923)
  • Design System: Add portable agent skills. (80597)
  • Docs: Add Background image control Readme. (69409)
  • Docs: Add Block Editing Mode Readme. (69411)
  • Docs: Fix broken link to the Document-Isolation-Policy explainer. (81790)
  • Docs: Fix broken link to the getEntityRecords selector reference. (81791)
  • Docs: Fix broken links to the Block APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. reference guides. (81571)
  • Docs: Fix broken skip ahead anchor on the custom block editor guide. (81835)
  • Docs: Fix dead link in the dynamic blocks tutorial. (81399)
  • Docs: Narrow the tsconfig split guidance to the standard layout. (81828)
  • Docs: Require site editor features to land in the extensible site editor too. (81752)
  • Fix Broken Links in Package file. (81700)
  • Fix broken documentation link in accessibility.md file. (81832)
  • PHPCSPHP Code Sniffer PHP Code Sniffer, a popular tool for analyzing code quality. The WordPress Coding Standards rely on PHPCS.: Refactor parameter type hints and clean comments. (81898)
  • Schemas: Document what the theme.json schema checks. (81773)
  • Storybook: Add Story for InnerBlocks. (68651)
  • Storybook: Add Story for BlockPopover. (68681)
  • Storybook: Add Story for URLPopup component. (68449)
  • Storybook: Fix default background color for Example Application theme story. (81765)
  • Storybook: Upgrade to 10.5. (80692)
  • UI: Add initial agents guidance mapping to contributing guidelines. (81400)
  • UI: Mark Autocomplete, Field, and Fieldset as recommended. (80636)
  • UI: Mark Input-related components as recommended. (81658)
  • UI: Move controlled prop guidance to contributing documentation. (82044)
  • Update coding guidelines to recommend TypeScript. (81763)
  • Update save & submit documentation. (81077)
  • Update broken links in document files. (81961)

Code Quality

  • Docs: Align param tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) columns in test/ docblocks. (81905)

Components

  • BorderControl, BorderBoxControl: Migrate styles to CSS Modules. (80437)
  • ComboboxControl: Narrow onChange callback type to string | null. (81568)
  • DataViews: Use Menu from @wordpress/ui. (81783)
  • DataViews: Vendor ValidatedComboboxControl. (81449)
  • DataViews: Vendor ValidatedFormTokenField. (81451)
  • DataViews: Vendor ValidatedToggleControl. (81492)
  • DataViews: Vendor ValidatedToggleGroupControl. (81450)
  • Fix DataViews list layout color token usage. (81074)
  • Migrate ComboboxControl to SCSS module. (80471)
  • Migrate DropdownContentWrapper to SCSS module. (81522)
  • Migrate GradientPicker, ColorPalette to SCSS module. (80473)
  • Migrate ProgressBar styles from Emotion to SCSS module. (80512)
  • Migrate ResizableBox to SCSS module. (81792)
  • Migrate Scrollable to SCSS module. (80694)
  • Migrate StyledLabel to SCSS module. (80001)
  • Migrate ZStack styles from Emotion to SCSS module. (80514)
  • Migrate BoxControl to SCSS module. (80715)
  • Migrate TextareaControl to SCSS module. (81353)
  • Storybook: Add missing @types/jest devDependency. (82017)
  • Storybook: Keep Vitest story scanning independent of the Vite root. (82020)
  • Theme: Rename ThemeProvider wrapper CSS class from root to wrapper. (81996)
  • Theme: Update Terrazzo packages to 2.7.1. (81978)
  • TypeScript: Bring the remaining route projects under the typecheck run. (81847)
  • UI: Add ControlWithError component. (81574)
  • UI: Add ValidatedInputControl component. (81627)
  • UI: Add ValidatedTextArea control. (81984)
  • UI: Update Base UI to 1.7.0. (81390)
  • Update Ariakit packages (0.4.35 => 0.4.37). (81080)
  • Update Terrazzo packages to 2.5.0. (81082)

Block Library

  • Block API: Address review feedback on block keyboard shortcuts. (81621)
  • Block API: Declare block keyboard shortcuts on variations and transforms. (81588)
  • Stop saving Table of Contents output. (80404)
  • Tabs: Number generated tab IDs from 1 and keep them sequential. (81781)
  • Playlist: Remove block toolbar sharing between parent and child blocks. (81432)
  • Update waveform player dependency patchpatch A special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing.. (81454)

Post Editor

  • ActionItem: Move the more menu deduplication out of the Slot. (81507)
  • Block Editor: Never spotlight blocks in a preview. (81615)
  • Editor: Remove FlexItem usage from NoteCard. (81851)
  • Use WCInputControl alias for legacy InputControl imports. (81830)
  • Use WCTextareaControl alias for legacy TextareaControl imports. (81834)

Data Layer

  • Core Data: Allow keyless entities to be addressed without a record ID. (81857)
  • TypeScript: Drop redundant undefined casts for keyless entity record IDs. (82018)
  • Update is-plain-object to 5.1.0. (81926)

Block Editor

  • Add translator context to pseudo-state labels. (81770)
  • Remove leftover files. (81793)
  • refactor: Convert createColorHOC to functional component. (70408)

Dashboard

  • Dashboard widgets & Grid: Use kebab-case for CSS selectors. (82053)
  • Quick Draft widget: Drop a reference to a class that does not exist. (82064)

Media

  • Media Editor Route: Add missing dependency to media-editor route. (81845)

Fields

  • Migrate last remaining JSJS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. file to TS. (81808)

Boot

  • Migrate styles to CSS Modules. (81756)

Layout

  • Layout block supports: Cast numeric grid attributes before use. (81560)

Private APIs

  • DataViews: Add a lint rule preventing private API imports. (81478)

Global Styles

  • Style: Update color to use CSS variable in global-styles-ui. (79053)

Tools

Build Tooling

  • Build Scripts: Force tsc –pretty so CI reports the project behind global diagnostics. (81937)
  • Build Tools: Stop watcher process trees on shutdown. (81504)
  • Build: Emit TypeScript declarations with –noCheck. (81839)
  • Build: Fix ESM declaration resolution. (82022)
  • CI: Skip the package CHANGELOG check when only the CHANGELOG changed. (82069)
  • Components, DataViews, Editor, UI: Split tsconfigs into build and dev projects. (81515)
  • Dependency updates Aug 2026 (2). (81906)
  • Dependency updates Aug 2026. (81870)
  • Lint: Prevent private API imports in all bundled packages. (82015)
  • Packages: Split story package tsconfigs into build and dev projects. (81516)
  • Packages: Split tsconfigs for utility and mid-size packages. (81514)
  • Release: Improve changelog categorization. (81475)
  • Replace the Storybook test runner with the Vitest integration. (81918)
  • Storybook: Fix production build warnings. (81758)
  • Storybook: Upgrade Vite to 8. (81494)
  • Styles Route: Reference the api-fetch and html-entities projects. (81989)
  • Test: Add Vitest ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org, Emotion compilation, console, and snapshot parity. (81039)
  • TypeScript: Add typecheck script and split root tsconfig into build and dev solutions. (81499)
  • TypeScript: Put route projects under the typecheck run. (81829)
  • Validation: Update dependency-audit to 0.4.6 and ignore the dataviews ./wp bundle. (81928)

Testing

  • Automated Testing: Change Storybook default a11yAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) test to error on failure. (81597)
  • Block Library: Fix failing test in playlist block. (81950)
  • E2E: Replace flaky router styles screenshot assertions. (81739)
  • List View: Fix flaky global shortcut test and re-enable it. (81690)
  • Perf: Report the first block selection as its own metric. (81616)
  • Test: Port shared Vitest test environment. (81038)
  • Tests: Make PHPUnit tests independent of test configuration flags and theme root. (79159)
  • Vitest: Resolve @flakiness/vitest reporter to an absolute path. (81582)
  • end-to-end Tests: Use str_starts_with()/str_contains() in hide-user-rest-routes plugin. (82030)

Data Layer

  • Update 23.8 release changes on trunktrunk A directory in Subversion containing the latest development code in preparation for the next major release cycle. If you are running "trunk", then you are on the latest revision.. (81485)

ESLint plugin

  • Remove fixable on i18n-no-flanking-whitespace. (70279)

First-time contributors

The following PRs were merged by first-time contributors:

  • @benazeer-ben: Add command: View post. (66720)
  • @dhruvikpatel18: Storybook: Add Story for URLPopup component. (68449)
  • @josephfusco: Add __unstable_wp_sync_storage filter for pluggable storage backends. (81697)
  • @konnen916: URL: Stop normalizePath throwing on a malformed percent sequence. (81086)
  • @sanketio: Accordion Heading: Route theme.json spacing to the toggle button. (81976)
  • @vedant-ere: Fix: Skip empty block markup in navigation to prevent split UL elements. (78793)

Contributors

The following contributors merged PRs in this release:

@aaronrobertshaw @aduth @afercia @amitraj2203 @andrewserong @annezazu @arthur791004 @benazeer-ben @ciampo @coderGtm @dhruvikpatel18 @dilipom13 @ellatrix @getdave @giteshsarvaiya @gregsullivan @hbhalodia @i-am-chitti @im3dabasia @Infinite-Null @ingeniumed @jasmussen @jeremyfelt @jeryj @jorgefilipecosta @josephfusco @jsnajdr @juanfra @Kgupta62 @konnen916 @MaggieCabrera @Mamaduka @manzoorwanijk @maxschmeling @mirka @mukeshpanchal27 @Mustafabharmal @ntsekouras @oandregal @ramonjd @retrofox @sanketio @sarthaknagoshe2002 @scruffian @shail-mehta @shimotmk @simison @sirreal @Soean @swissspidy @t-hamano @tellthemachines @timse201 @USERSATOSHI @vedant-ere @youknowriad

Props

Thanks to @mciampini and @aduth for helping with the npm package distribution and stable release, @manzoorwanijk, @onemaggie and @softglaze for release candidaterelease candidate One of the final stages in the version release cycle, this version signals the potential to be a final release to the public. Also see alpha (beta). support and testing, @coreyhall93 for the video highlights, and @tyxla, @ramonopoly, and @ellatrix for reviewing this post.

#block-editor, #core-editor, #gutenberg, #gutenberg-new

Dev Chat Agenda – September 2, 2026

The next WordPress Developers Chat will take place on Wednesday, September 2, 2026, at 15:00 UTC in the core channel on Make WordPress Slack.

Dev chat is back on Wednesdays again!

The live meeting will focus on the discussion for upcoming releases, and have an open floor section.

The various curated agenda sections below refer to additional items. If you have ticketticket Created for both bug reports and feature development on the bug tracker. requests for help, please continue to post details in the comments section at the end of this agenda or bring them up during the dev chat.

Announcements 📢

7.2

7.1.1

General

Discussions 💬

The discussion section of the agenda is for discussing important topics affecting the upcoming release or larger initiatives that impact the CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. Team. To nominate a topic for discussion, please leave a comment on this agenda with a summary of the topic, any relevant links that will help people get context for the discussion, and what kind of feedback you are looking for from others participating in the discussion.

Open floor  🎙️

Any topic can be raised for discussion in the comments, as well as requests for assistance on tickets. Tickets in the milestone for the next major or maintenance release will be prioritized.

Please include details of tickets / PRs and the links in the comments, and indicate whether you intend to be available during the meeting for discussion or will be async.

Props to @audrasjb for collaborating on this agenda.

#7-1, #7-2, #agenda, #core, #dev-chat

WordPress 7.1.1 Release Schedule

Since WordPress 7.1 was released, contributors have kept a close eye on incoming reports to the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ Support Forums, TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress., and the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ repository on GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/. The volume and severityseverity The seriousness of the ticket in the eyes of the reporter. Generally, severity is a judgment of how bad a bug is, while priority is its relationship to other bugs. of tickets mean that the maintenance release should be prepared habitually.

This release will be co-led by @adamsilverstein, @adrianduffell, and @andraganescu.

Schedule

Date/TimeEvent
Thursday, September 3, 2026 at 14:00 UTCBug Scrub
Friday, September 4, 2026 at 14:00 UTCBug Scrub
Tuesday, September 8, 2026 at 20:00 UTCBug Scrub. WordPress 7.1.2 Milestone will be opened, and some tickets may be punted.
Wednesday, September 9, 2026 at 10:00 UTCBug Scrub
Thursday, September 10th, 2026 at 17:30 UTCWordPress 7.1.1 RC1
Tuesday, September 15, 2026 at 14:00 UTCBug Scrub.
Thursday, September 17, 2026 at 15:00 UTCWordPress 7.1.1 General Release

Note that the above times are estimates – exact times for scrubs, RCrelease candidate One of the final stages in the version release cycle, this version signals the potential to be a final release to the public. Also see alpha (beta). and General release will be announced in the 7.1 Release Leads room and will be based on availability of individuals helping with the release.

Targeted Fixes

WordPress 7.1.1 is intended as a bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority.-fix only maintenance release. Tickets will be included provided they are issues introduced during the 7.1 cycle or intentionally deferred at the end of the 7.1 cycle. You can follow trac report 4 or the 7.1.x editor tasks board for proposed fixes.

Get Involved with 7.1.1

Bug Scrubs will happen in the #core room during the times posted above. Each of the open tickets is going to require development work along with testing and review. You can also run your own scrubs to help ensure that all of the correct tickets are fixed in this release. Additionally, some locales have strings in 7.1 in need of translation.

General coordination for the release will happen in the 7.1 Release Leads room and decisions around code for the release will be made in the #core room.

Props to @jorbin and @adrianduffell for reviewing this post.

#7-1, #7-1-1, #7-1-x, #minor-releases

X-post: Updates to the WordPress Vulnerability Disclosure Program

X-comment from +make.wordpress.org/security: Comment on Updates to the WordPress Vulnerability Disclosure Program

X-post: The Core Security Initiative

X-comment from +make.wordpress.org/security: Comment on The Core Security Initiative

Proposal: A Secrets API for WordPress 7.2

WordPress has no first-class way to store a credential. This proposal outlines a Secrets APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. for 7.2, along with WP-CLIWP-CLI WP-CLI is the Command Line Interface for WordPress, used to do administrative and development tasks in a programmatic way. The project page is http://wp-cli.org/ https://make.wordpress.org/cli/ support for it, and explains why the accompanying UIUI User interface should wait for 7.3.

Why it matters

Every pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. that needs an API key today writes it to the options table in plaintext. That is the only available path, so this isn’t a criticism of plugin authors. The consequence is that credentials end up in the same table as the site tagline, and therefore in every database dump, every backup, every staging clone, and every wp option get in a shared terminal.

Plugins have been solving this independently for years, each with its own key derivation, its own cipher choice, and its own failure modes. Site Kit encrypts its Google credentials. WooCommerce gateways handle payment keys. SMTP plugins hold mail credentials. Each one is a separate audit surface, and none of them can be reviewed once on behalf of the ecosystem.

This was survivable when the average site held a Mailchimp key and a reCAPTCHA secret. AI service integrations have made credentials both more numerous and far more expensive to lose: a leaked model-provider key is a metered spend liability. The blast radius increased while the storage mechanism stayed the same.

A second gap is that site owners and hosts increasingly need to answer basic operational questions — which credentials exist on this site, what code is using them, when were they last rotated. None of those are answerable today, because there is no object to ask about. A credential is just a row in a key-value store.

CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. has no concept of a secret; there’s nothing for either problem to attach to.

Clarifying priorities

A tightly-scoped, stable API landed in 7.2 helps push forward on requirements like those documented in the Security Audit for the Connectors screen.

No new UI in 7.2. The storage and retrieval semantics are the part that must be right the first time, because every plugin, every CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress. command, and every future adminadmin (and super admin) screen inherits them. A settings screen can be designed properly in 7.3 once there’s a stable API to build against and real usage to design from. The hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. and accessors an admin screen would need are in scope now; the screen itself is not.

WP-CLI is in scope. It gives the API a first-party consumer inside the same release, which is the most reliable way to discover whether the surface is actually usable before it freezes. It also closes a real leak of its own: commands that accept credentials as arguments expose them in shell history and in the process list on shared hosts. Reading and writing through the API fixes that in the same change.

A feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins ships before the core patchpatch A special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing.. Rather than propose an API and ask people to evaluate it from a design document, I’ll publish the implementation as a plugin first. This will let contributors run the API instead of reading about it, expose the awkward parts of the surface while they’re still inexpensive to change, and give sites on 7.0 and 7.1 something usable immediately rather than waiting for December. The core patch then follows with an API surface identical to the plugin’s; nothing anyone builds against it needs rewriting.

The plugin will prove out the API before we consolidate things into core.

Proposed API

A small function set, a value object, and always-on encryption.

wp_set_secret( string $name, string $value ): bool|WP_Error
wp_get_secret( string $name, string $version = WP_Secret_Version::CURRENT ): WP_Secret|null|WP_Error
wp_delete_secret( string $name ): bool|WP_Error
wp_import_option_as_secret( string $option, string $name ): bool|WP_Error

WP_Secret::reveal(): string
WP_Secret::fingerprint(): string

At a call site:

wp_set_secret( 'my-plugin/api-key', $key_from_form );

$secret = wp_get_secret( 'my-plugin/api-key' );

if ( is_wp_error( $secret ) ) {
    // Exists, but unusable. Key material changed. Tell the user.
} elseif ( null === $secret ) {
    // Doesn't exist. Show the connect flow.
} else {
    $client = new API_Client( $secret->reveal() );
}

Supporting surface:

  • Secrets are namespaced by convention, plugin-slug/secret-name, so a future admin screen can group by owner and cross-namespace access has something to check against.
  • WP_Secret masks itself in logs, var_dump(), and error output. Getting the raw string requires an explicit ->reveal(), which makes every point of use greppable.
  • Default storage is the options API — ciphertext blobs, autoload=no, excluded from options.php and the REST settings endpoint. The same relationship the object cache has to options: the default substrate, replaceable by a drop-in.
  • Two capabilitiescapability capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability)., manage_secrets and manage_network_secrets.
  • A change hook fires on write, carrying actor, timestamp, and old and new fingerprints. Fingerprints are readable; values are not.

Design decisions most likely to draw objections follow, with rationale.

Encryption is not optional

Secrets are encrypted at rest under a master-key envelope: a per-secret data key, wrapped by a master key. There is no plaintext mode and no constant to disable encryption.

The obvious objection is data loss — a site rotates its salts or migrates hosts, key material changes, and the secrets no longer decrypt. Plaintext options never do that. With an envelope, individual secrets are encrypted under a random master key, and the site key only wraps that master key. Rotation re-wraps a single value (the master key) without touching stored secrets. A dedicated constant is the preferred key source, with a zero-config fallback derived from existing salts for sites that can’t set one. When key material really is gone, the failure is bounded and visible: Site Health reports undecryptable secrets, and the recovery path is to re-enter them. Nothing is silently corrupted.

Site Kit is the empirical case. It derives from LOGGED_IN_KEY and LOGGED_IN_SALT by default, recommends a dedicated constant, and documents that salt rotation breaks stored credentials — and it has shipped that way at enormous scale. The ecosystem’s response was to document the approach, not to reject it.

Rationale: an API that can be configured to store plaintext is an options API with a misleading name. Making encryption unconditional is what lets a plugin author make a claim to their users about how the key is stored. The alternative — encryption off unless a site opts in — protects the small number of sites that rotate salts by leaving everyone else in plaintext forever. Sites that would opt in are largely the sites already capable of running a drop-in. Sites that would not are exactly the ones the API exists for.

Availability of cryptographic APIs is not a concern: libsodium has been bundled with PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher since 7.2, and core additionally ships sodium_compat for the cases where the extension has been disabled at build time. The primitives are present on every supported configuration without a new dependency.

Retrieval returns one of three things

wp_get_secret() returns a WP_Secret on success, null when the secret does not exist, and WP_Error when it exists but could not be retrieved — wrong key, unavailable keyring, failed decryption.

Rationale: collapsing “absent” and “broken” into a single false-y value is how you get a site that erroneously re-runs its onboarding flow, or disables an integration, when the real problem is key management. Separating them is also what lets a site distinguish a missing credential from an unauthorized change to key material.

No filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. on the retrieval path

There is no filter applied to a secret on its way out of storage. No endpoint, filter, or capabilitycapability capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability). returns a secret’s value other than the API call itself.

Rationale: I expect the most pushback here — a filter on secret retrieval is, by construction, a hook that receives every credential on the site in plaintext. Any plugin could register it, making it a documented interception point. A filter that can intercept a credential is a filter that can steal one. The flexibility WordPress normally gets from filters is provided instead through explicit, replaceable providers, described next.

Two extension points, independently replaceable

A drop-in, secrets.php, exposes storage and keyring as separate extension points: where ciphertext is stored (Vault, Parameter Store, a host API) and what wraps the master key (a KMS, an HSM). Neither is ever handed a plaintext secret, and neither can turn encryption off.

Rationale: these are different concerns and sites have different constraints. Replacing only the keyring while keeping default storage is a reasonable configuration, and so is the inverse. Coupling them into one swap would force an all-or-nothing decision that most sites can’t make, and would push people back to storing credentials in options.

Two version slots, not unbounded history

CURRENT and PREVIOUS, modeled as string constants on a final class WP_Secret_Version rather than a native enum. Overwriting a secret keeps the old value recoverable, so a mistyped key is fixable. Requests already in flight won’t fail mid-rotation. Retiring the previous slot is an explicit operator action — no timers, no cron.

Rationale: named version history would keep every credential a site has ever held recoverable from a backup indefinitely. Two slots covers the real use case. Retirement is operator-driven because core has no way to know when a third-party integration has finished draining the old value; a timer would just guess wrong on a schedule. Native enums require PHP 8.1, and while 8.3 or better is the recommended version, core’s minimum remains 7.4 — so string constants on a final class are the portable equivalent.

Multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site is in v0

Networknetwork (versus site, blog)-level secrets are supported. Salts are network-wide, so distinct option rows would give logical separation and no cryptographic separation; instead a network root key derives per-site subkeys via sodium_crypto_kdf_derive_from_key(). Site secrets and network secrets are separate functions with separate capabilities, and there is no implicit fallback from one to the other.

Rationale: adding this later would mean introducing a second key hierarchy alongside the first, and migrating between them. The useful consequence of doing it now: rotating the key on a 500-site network re-wraps one value rather than 500.

Import, don’t migrate

No automatic sweep of the options table. wp_import_option_as_secret() lets a plugin author move one known option deliberately, on their own explicit upgrade schedule — and flags the imported secret for rotation rather than merely reporting success.

Rationale: core cannot reliably tell which options are credentials, and guessing would break sites in ways close to undebuggable. The rotation flag matters just as much: a credential that has been sitting in wp_options is already in backups, replicas, and object caches, and encrypting it now does not change that. Rotating is what actually fixes it.

Other decisions worth stating

  • Strings in, strings out. The API does not serialize. Nothing stops a plugin from json_encode()-ing something and storing the result, but core neither encourages it nor unpacks it, so a secret can never expand into an object graph on read.
  • Fail closed. If an external store or key backend is unreachable, reads and writes return an error. There is no fallback to local storage or local key wrapping.
  • Nothing plaintext enters the object cache. On shared hosting a persistent object cache is shared infrastructure. WP_Secret refuses serialization outright.
  • No export. Values are write-only. Migrations and staging pushes mean re-entry at the destination, so staging never holds production credentials. Fingerprints let an admin confirm the re-entered value matches.

What this does and does not do

The API is a hardening interface. If a secret lives in the WordPress database and a function exists to decrypt it, then any code running as WordPress can obtain that secret.

In scope: database dumps and exfiltration, backups sitting in cloud storage, SQL injection reading wp_options, careless disclosure surfaces — options.php, export files, support screenshots, screen shares, debug logs — and a compromised read-only replica.

Out of scope: code execution in the WordPress process. Nothing defends against that. Code running inside WordPress can call wp_get_secret() for the same reason it can read environment variables or wp-config.php — the secret has to be usable, so anything that is WordPress can use it. Registering a secret against a plugin slug does not prevent a different plugin from asking for it; slugs aren’t authenticated, and even a perfect allowlist wouldn’t stop code that reads the revealed value out of memory after a legitimate call. This proposal makes no claim of per-plugin isolation, and masked values are hygiene against shoulder-surfing rather than a privilege boundary.

What changes is the value of a stolen database, which is the overwhelmingly more common breach.

What it does provide:

  • Credentials are not sitting in plaintext in a table that gets dumped, cloned, and shared.
  • Access has one chokepoint, which makes it loggable and auditable for the first time.
  • Rotation and retirement are defined operations rather than an UPDATE and a hope.
  • The storage extension point lets a host or site owner move secrets out of WordPress — which is the only configuration where real per-caller enforcement becomes possible.

Prior art

Timeline

Beta 1 for 7.2 is October 20–22, which is the practical deadline for an API landing in this release. Working backward:

  • Now through mid-September: feedback on this proposal, particularly the questions below. Feature plugin published for testing.
  • Late September: patch on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress., with the API surface matching the plugin.
  • Before BetaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 1: committed, or explicitly deferred to 7.3 rather than rushed in.

I’ve volunteered for technical contributions to 7.2 and intend to do this work rather than propose it and hand it off.

Feedback wanted

Objections now, while the surface is still cheap to change. Specifically:

  1. The no-filter decision on retrieval. Providers are meant to cover what a filter would normally give you — is that substitution sufficient for the cases you’d actually need to hook?
  2. Two version slots. Is CURRENT/PREVIOUS sufficient, or is there a rotation pattern that genuinely needs more?
  3. Import, not migrate. Plugin authors: does wp_import_option_as_secret() fit how you would actually move an existing key, or does it need a different shape?
  4. WP-CLI surface. Which commands most need this, and in what order?
  5. Hosts. If you run a real secret store or a real key backend and the drop-in surface is missing something you’d need, that’s the most useful feedback available — and much easier to add before anything ships than after.

Any feedback is welcome — please share your thoughts in the comments below.

Props to @jeffpaul, who talked me into building the original proof of concept six months ago, and @whyisjake for shepherding this proposal.

#proposal