Migrating From WordPress After PHP2Shell: Patch First, Then Decide What to Bring
PHP2Shell is fixed by a PHP update, not a migration. When a site cannot move to newer PHP, the move becomes a fair comparison. What the WordPress export carries, what plugins leave behind, and how an AI agent fills the gap.


Bring the posts, the pages, the categories and the URLs. Leave the plugins, the theme and most of what the plugins produced. That is the short version of a WordPress migration to a hosted builder. The export file WordPress gives you carries the content; everything that was a plugin's job has to be done again by the new platform, or not at all. The decision for each piece is the work.
This post is part of our guide to Migrating a Website With AI.
October 2026: PHP2Shell, and why it is not a reason to migrate this week
Updated 22 October 2026.
Patch PHP first
If you are reading this because of the PHP security release, start here. A migration takes weeks. The fix for this takes hours, and it is not a WordPress update.
On 21 October 2026 the PHP project released PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two vulnerabilities, CVE-2026-109618 and CVE-2026-109619, which researchers nicknamed PHP2Shell. PHP's own advisories (GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp) rate both critical, 9.2 on CVSS v4, and describe unauthenticated remote code execution with the web worker's privileges. Remote code execution was confirmed against Apache with mod_php using default PHP limits, and the session path was also validated against PHP-FPM.
What this means for a WordPress site, per the WordPress.org announcement:
- The flaws are in PHP, not WordPress. They affect any server that runs a PHP application, and no WordPress update is required or planned. Updating WordPress, a theme or a plugin does not fix them.
- Check your PHP version under Tools, then Site Health, then Info, then Server.
- PHP before 8.2 no longer gets security updates from the PHP project. If you run an older version on a server you manage yourself, WordPress.org repeats the advice of several national cyber security agencies: consider taking the server offline while you prepare to update.
PHP's advisories are direct about the rest: updating to a patched release is the only complete mitigation. Turning off session.upload_progress.enabled blocks the demonstrated session path, and the advisory still calls it partial. Cloudflare deployed firewall rules for every plan with its WAF on, including Free, from 03:02 UTC on 21 October, and its own post tells customers to patch PHP anyway. A firewall buys time; it does not change the version.
So this week the order is: ask your host whether the patched PHP is installed, confirm the version yourself in Site Health, and if you manage the server, update PHP and restart every worker. Managed WordPress hosts did much of this on the day. Some, such as WordPress.com and its sister services, said their customers were already protected, as The Repository reported.
One more reason to patch first even if you have already decided to move: the old site stays live for the whole migration, usually several weeks, and both the agent and any importer will be reading it. An unpatched site is not a safe place to leave running while you rebuild somewhere else.
When it does become a migration question
The patch closes this incident. The question it leaves behind is who keeps the layer under your site current, and whether they can. The Repository put the share of WordPress sites on PHP versions the project no longer patches at about 35%. PHP 8.2, the oldest branch that got this fix, reaches the end of its security support on 31 December 2026, per PHP's supported versions page.
If your site can move to PHP 8.3 or later with a test and a backup, do that and stay. If it cannot, because a theme or a plugin breaks on newer PHP and nobody maintains it, you are already choosing between two projects: an upgrade that replaces the theme and plugins, or a move to a platform where the runtime is not yours to run. That is the point where a migration is a fair comparison, and the rest of this post is how to weigh it. When Not to Migrate covers the sites that should still stay.
A quick way to see which side you are on: list every active plugin and theme, and next to each write its last update date and whether its page declares support for PHP 8.3 or later. A list where everything is current means the PHP upgrade is a routine job. A list with three abandoned plugins doing important work is the real reason the site is stuck, and those three rows are what a migration would have to replace.
What the export file contains
WordPress exports content from Tools, then Export. The result is a WXR file, which is XML, and the Tools Export documentation lists what goes into it: posts, pages, custom post types, comments, custom fields, categories, tags, custom taxonomies, users and navigation menus. You can export everything or filter posts by category, author, date range and status.
What the documentation does not list, and what you should not expect in the file, is the media library as files, the theme, the plugins or their settings. Image URLs are in the post content, pointing at the old site. The images themselves are still on the old server. That matters for the order of operations: fetch the images while the old site is up.
Custom fields are in the file, but they only mean something to the plugin that wrote them. A field called _yoast_wpseo_metadesc is your meta description; a field called _elementor_data is a page layout in a format nothing else reads.
The export file is still worth taking even if you never import it anywhere. It is the complete record of what the site had, drafts included, and it is the best source for the content inventory.
What travels well
- Posts. Title, body, date, author, categories and tags. This is the part of a WordPress site a hosted builder can take almost as is. Body HTML from the classic editor and the block editor both come across as text with headings, lists, links and images.
- Pages. Title and body. If a page was written in the editor, it travels. If it was assembled in a page builder plugin, the body is often empty or a wall of shortcodes, and the page has to be rebuilt.
- URLs. The slug of each post and page is in the file. Keep them wherever the new platform allows it. A post at
/blog/our-new-office/that becomes/post/our-new-officeneeds one row in the redirect map; the same post at the same path needs none. - SEO titles and descriptions. Usually in custom fields written by an SEO plugin. An agent can read the field for each post and carry it over as the meta title and description on the new platform.
What does not travel
- The theme. Layout, colors, fonts and widgets are not content. The new site gets a new design. This is usually why the migration is happening.
- Plugins. Contact forms, galleries, sliders, tables, event calendars, membership, caching, security. Each one is either a feature of the new platform, a feature you no longer need, or a reason not to migrate. The table below goes through the common ones.
- Page builder layouts. Elementor, Divi, WPBakery and the like store layouts in their own formats. The content inside them is sometimes recoverable from the rendered page, which is why an agent reading the live site is more useful than an agent reading the export file for those pages.
- Comments. They are in the file, but most hosted builders have no comment system. Decide whether the comments mattered. On most small business blogs they did not.
- Users. Accounts and roles are specific to WordPress. Author names are worth keeping as author records on the new site.
- Form entries. Messages people sent through a form plugin live in the WordPress database, not in the export file. Export them from the plugin before the old site goes away.
- WooCommerce. Products, orders and customers are a separate migration with its own export, and a hosted builder with a products catalog is a different shape from a cart with checkout. Treat it as its own project.
Importing the posts into Beste
For the blog, you do not need the export file or an agent. Beste imports WordPress posts directly from the Posts panel in Studio, reading them from the site's REST API, which is the interface WordPress publishes for exactly this kind of job.

What comes across for each post:
- The post itself. Title, content, excerpt and publish date.
- Who and where. The author, the categories and the tags.
- Images. The featured image and the images in the content are copied into the Beste media library. They no longer depend on the old server, which removes the deadline that usually hangs over a migration: the images are safe the moment the import finishes, not the day you remember to download them.
- The slug. Each post keeps its WordPress slug, so the redirect map stays simple.
Two behaviors are worth knowing before you run it.
Imported posts arrive as drafts. Nothing appears on your live site until you publish it. That gives you a natural review step: read each post on the new design, fix anything that rendered oddly, and publish in batches. A post that used a shortcode or a page builder block may need a section rebuilt by hand or by the agent; reading the imported draft is how you find out which ones.
Running it again syncs instead of duplicating. If a post with the same slug already exists on Beste, the import updates it rather than creating a second copy. That changes how you plan the move. You can import early, build and review the rest of the site while the old blog keeps publishing, and run the import once more just before launch to pick up the newest posts and any last edits. There is no content freeze and no list of "posts written after the export" to recreate by hand.
Three things the import needs from the old site:
- It has to be up. The import reads the live site, so run it before you switch the domain, and keep the old host running until you have checked the result. This is one more reason to have PHP patched first.
- The REST API has to answer. Some security plugins switch it off or restrict it. If the import finds nothing, check that first; it is usually a setting in the plugin, and you can turn it back on for the duration of the move.
- The posts you want have to be published. Plan on bringing published posts, and decide separately what to do with drafts you still care about.
What the import does not do is decide your URLs. The slug is kept, but the path around it follows Beste's post pattern, /post/slug. If your WordPress blog lived at /slug/, /blog/slug/ or /2019/05/14/slug/, every post still needs one redirect row, and because the slug is the same on both sides, those rows are the easiest in the map: the agent can generate the whole set by changing the prefix.
Bring your WordPress blog to Beste
Import your posts with their images from the Posts panel in Studio. They arrive as drafts on your new site, and nothing goes live until you publish.
Plugin by plugin: what replaces it
Most small WordPress sites run the same dozen kinds of plugin. This is how each maps to a hosted builder, using Beste as the concrete case. A row that says "nothing equivalent" is a row to read When Not to Migrate about.
| On WordPress | On Beste | Notes |
|---|---|---|
| SEO plugin (Yoast, Rank Math) | Meta title and description fields on every page and post; sitemap, OG images and structured data generated on publish | Robots.txt is editable in SEO Settings. |
| Schema or local SEO plugin | Entity identity in Studio: Organization, Person or LocalBusiness, with sameAs links, added to every page | Set once; see the agent-ready page. |
| Contact form plugin | Dynamic forms | Submissions are saved in the dashboard on every plan; email delivery is Pro. Response export is not available yet. |
| Gallery, slider, tabs, accordion | Sections from the library | Nothing to install or update. |
| Multilingual plugin (WPML, Polylang) | Multi-language support: more than 50 languages, a clean URL per language, hreflang on linked pages | No fee per language. |
| Caching, CDN, image optimizer | Nothing to set up | Pages run on an edge network and images are resized when requested, per the hosting page. |
| Security, firewall, backup of core files | Nothing to run | There is no server, plugin or core on your side to patch. |
| Analytics, Tag Manager, Meta Pixel | Integrations by pasting an ID in Settings | Pro, Team and Business. |
| Cookie banner | Cookie consent banner | Pro, Team and Business. |
| Maintenance mode, password protect | Site protection switches | Pro, Team and Business. |
| Redirection plugin | Bulk 301 redirects from a CSV, single redirects in the editor or over MCP | Pro. Export the old plugin's rules and add them to the new map. |
| Small WooCommerce shop | Products catalog with options and variants, checkout through a Stripe payment link, a quote, WhatsApp or Shopify | Beste does not process payments. A large store stays on a commerce platform. |
| Membership, LMS, bookings, directory | Nothing equivalent | Beste builds websites, not apps. Keep the app where it is. |
Two rows deserve a second look. The redirection plugin is easy to forget, and its rules are old redirects that still carry traffic; export them and fold them into the new map so nothing chains. And the contact form: once the old site is switched off, its stored messages go with it.
The two-source method, for everything that is not a post
The importer covers the blog. Pages, page builder layouts and anything a plugin rendered still need the agent, and the best inventory of those uses both the export file and the live site, because each has what the other lacks. The export file has every page, including drafts, with dates and custom fields. The live site has the rendered content of page builder pages, the actual image files, and the URLs as served, with trailing slashes and redirects already in place.
Give the agent both. Ask it to build the inventory from the export file, then fetch each published URL and fill in what the file left out: the rendered text for builder pages, the image files, the final URL after any redirect the old site already had. The method is in Content Inventory With an AI Agent. Keep the posts in the inventory too, even though the importer moves them; their old URLs are what the redirect map is built from.
URLs: the WordPress-specific traps
- Date-based permalinks.
/2019/05/14/post-name/cannot usually be reproduced on a hosted builder. Every post needs a redirect row. - Category and tag archives.
/category/news/and/tag/wordpress/are index pages. Decide as a group whether they redirect to the new blog index or return 404. - Pagination.
/page/2/,/page/3/on the blog and on archives. Usually 404. - Attachment pages. WordPress gives every uploaded image its own page. These are almost never worth keeping, and they are often indexed. Let them 404.
- Feeds.
/feed/and per-category feeds. If anyone subscribed, redirect to the new feed; otherwise 404. ?p=123URLs. Old links sometimes use the numeric ID. The export file has the ID for each post, so the agent can add those rows too.- Uploads. PDFs and images under
/wp-content/uploads/are sometimes linked from other sites. If Search Console shows clicks to them, upload the files again and redirect the old paths.
How the rows become redirects is in Redirect Mapping From a CSV.
The order of work, start to finish
- Patch first. Confirm the PHP version in Site Health and that your host has applied the 21 October fix. The old site has to stay up for weeks.
- Export. Tools, then Export, all content. Search Console pages with clicks over 12 months. The redirection plugin's rules and the form plugin's entries.
- Inventory. The agent merges the export and the live site into one list; you decide keep, merge, rewrite or drop.
- Import the posts. From the Posts panel in Studio. They arrive as drafts with their images copied over; read them on the new design and publish when ready.
- Pages. Rebuilt from sections, by the agent page by page with the old text as written, or from a prompt and then filled in.
- Settings. Meta titles and descriptions per page, entity identity, robots.txt only if you had custom rules, forms, integrations.
- Redirects. The CSV built from the inventory, checked in the import preview. Posts with the same slug need only the prefix changed.
- Run the post import once more. Same slugs update in place, so new posts and late edits come across without duplicates.
- Launch. Point the domain, turn site-wide noindex off, publish, submit the sitemap in Search Console.
- Keep the old site patched and reachable until you have checked the result, the form entries are exported and the redirects have resolved from the new host for a few weeks.
What the agent does, and what you do
The importer moves the posts. The agent does the rest of the mechanical work: it parses the export file, builds the inventory, fetches the live pages, pulls out meta titles and descriptions from the custom fields, downloads the images used on pages, and creates pages on the new platform with matching slugs. That is hours of repetitive work it does not get tired of.
You decide what the pages built in a page builder should look like on the new platform, which plugins' features need an equivalent, and which old URLs are allowed to 404. You also read every imported post and every rebuilt page before publish. An importer and an agent both reproduce what they read, including the typo in the opening paragraph from 2017.
How this works in Beste
WordPress posts are imported from the Posts panel in Studio, as drafts, with their images copied into the media library and their slugs kept; a second run updates posts with the same slug instead of duplicating them. The built-in blog then gives each post an author, summary, tags, date and reading time as fields, with BlogPosting structured data and a sitemap entry on publish. Pages are rebuilt from sections in the library (what a block-based builder is, if the idea is new), by hand in the editor, from a prompt that describes the business, or by an agent over the MCP server using create_page and add_section with the slug set to match the old path. Every change the agent makes waits in the draft, and you publish when you have read it. Nested pages reproduce most old paths exactly. The redirect rows for the paths that could not be kept go into the CSV import on Pro, described on the technical SEO page; keep Pro while those redirects matter, because they stop working if the plan is cancelled. The site runs on hosting with HTTPS, CDN and platform updates handled by Beste, so there is no server runtime, plugin or core update for you to run afterwards. Once the posts are in, keeping the blog going from a conversation is covered in Running a Blog Through MCP.
Sources
Checked on 23 October 2026.





