Skip to content

Changelog#

Versions are listed newest first. The version of an install is the Version header of bb-migrate.php and the BB_MIGRATE_VERSION constant; both sites of a transfer should run the same one.

0.2.2 (2026-11-05)#

A security review of the push and pull paths. "Accept push" remains administrator-level access by design, and is no longer a route to code execution without "Allow code files". See Security.

Security#

  • Strict SQL allow-list. SQL received from another site must be one of the statement forms the exporter emits: DROP TABLE IF EXISTS, CREATE TABLE … ( and INSERT INTO … VALUES on _bbmig_ temp tables, plus the dump's session header lines. Statements are checked with every quoted literal blanked. This replaces a check on the statement's first keyword, which versioned comments, INSERT … SELECT, CREATE … SELECT, ALTER … RENAME and SET on global variables could pass. The list now applies to pulled dumps as well as pushed chunks.
  • Snippet option validation. A Custom CSS & JS snippet's options must describe a css, js or html snippet with a plain preprocessor ID, in packages, meta writes and the snippets action. Before, language=php produced a PHP file under uploads.
  • Uploads rule. The uploads scope refuses an executable extension anywhere in a file name, .htaccess, .user.ini, web.config, php.ini, and all dotfiles.
  • Path containment. Every read, write and delete checks the resolved path against the resolved scope root.
  • No object instantiation on import. Packaged meta is unserialized with allowed_classes => false. Attachment paths and size file names in a package must be valid upload paths.
  • The receiver keeps its own key and switches. bb_migrate_settings is restored after every import whatever the sender asks, and active_plugins is kept on a push unless "Allow code files" is on. Options named bb_migrate_… are left out of every export, backup and push.
  • Backup names withheld. The pre-push backup's file name is no longer returned to the pushing site.
  • The mu-plugin verifies the signature, on its own route only. The compatibility mu-plugin (version 3) checks the HMAC itself before it disables anything, and matches only the plugin's REST path or rest_route value instead of any URL containing bb-migrate/v1.
  • File replay markers. Replay protection uses one marker file per signature, created exclusively, in uploads/bb-migrate/nonces/, instead of transients.
  • .dev is not local. Hosts under .dev no longer count as local sites, so overwriting their database asks for the host name or --yes.
  • The plugin's own folder is not a scope. plugin:bb-migrate is "Unknown scope" on both sides. New versions are installed by zip upload.
  • Client. Requests follow no redirects, plain http:// connections are accepted only to local-looking hosts, and private and loopback targets are refused unless the sending site is local.
  • Handshake and pulls list and export only the site's prefixed tables.
  • Admin screen. Strings supplied by a remote are escaped before rendering. Finished and failed jobs are deleted at once; the stale-job cleanup now matches the right option prefix.

Changed#

  • --yes confirmations. files push --delete, site activate, site deactivate, pages push --on-exists=update and meta push ask for confirmation on the command line unless --yes.

Added and fixed after the review (2026-11-06)#

  • Client retries on idempotent routes. The handshake, file routes, export routes, package listing and export, and backup steps are tried up to three times on a transport failure or a non-JSON 5xx or 429 reply. Imports and site actions are never retried.
  • Snippet URL-rules index rebuild. Regenerating snippets also rebuilds the custom-css-js-urls option, so a pushed snippet with "where on site" rules prints without being saved by hand on the destination.
  • Summary table fix. The pages result table no longer fails on rows without a URL (skipped and matched posts).

0.2.1 (2026-11)#

Fixes from the first deployment to a staging server.

  • A file push stops on the first file the receiver could not write and names it. 0.2.0 reported success when the receiver's folder was not writable by PHP and nothing had been written.
  • Files written by a push are left at mode 664 and new folders at 775, so an SFTP account in the web server's group can still edit them.

0.2.0 (2026-11-04)#

File sync by path, pruning, and the remote steps of a deploy.

  • Path-scoped file sync. --paths and --paths-file confine a sync to folders, files or globs inside the scope, so one file or folder travels instead of the whole tree.
  • Pruning. --delete removes files on the destination that the source no longer has: always available for theme and plugin scopes, for uploads only when the sync is confined to paths. The dry run lists copies and deletions. New route files-delete.
  • --purge purges the destination's cache after a sync.
  • Remote site actions. wp bb-migrate site: list, activate and deactivate plugins; show, set and copy BB Cache settings; purge; regenerate Custom CSS & JS snippet files. wp bb-migrate meta push: write single meta values on a remote post. New routes site-plugins, site-cache, site-snippets, site-meta, and a Site tab in the admin screen. The compatibility mu-plugin leaves site-* routes with the full site.
  • Page package improvements. An attachment can be an item on its own (by ID, upload path or URL). Snippet posts have their served files regenerated on import. Packaged meta is unserialized before it is stored; 0.1.0 stored ACF arrays double-serialized.

0.1.x#

The first versions.

  • Database export and import. Chunked export to .sql.gz with a metadata header, optional prefix rename and exclusions (transients, spam comments, revisions). Streaming import into _bbmig_ temp tables, swapped in with one RENAME TABLE, with a backup first and preserved options restored afterwards.
  • Find and replace. Serialized-safe, working on the serialized text and rewriting string lengths; JSON-escaped and URL-encoded forms of each pair; a standalone test in tests/replace-test.php.
  • Push and pull between two sites over signed REST requests, with the three per-site switches and automatic replacement pairs from the handshake.
  • File sync of whole scopes: uploads, themes, plugins.
  • Page packages as a zip, by push or by pull.
  • The compatibility mu-plugin, so a half-copied theme or plugin cannot break the transfer delivering it.
  • Admin stepper. Tools → BB Migrate, with a resumable job engine shared by the admin screen (one short request per step) and WP-CLI.