Summary
Main-site export archives can include tables belonging to other network sites. The importer then rewrites every source base-prefix table name, allowing unrelated source-site tables to be created under the target-site prefix. Existing-site imports can also emit database errors yet finish with a success message.
Evidence
- A main-site archive contained source tables for multiple subsites (
prefix_3_*, prefix_4_*, and similar), not only source main-site tables.
- Importing that archive into an existing target site created 5,898 target-prefixed tables, including names derived from unrelated source-site prefixes.
- The import logged 125
table already exists errors but reported successful completion.
- The target required manual quarantine and a table-scoped recovery.
Files to modify
inc/site-exporter/mu-migration/includes/commands/class-mu-migration-export.php — derive the export table set from the requested blog only.
inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php — validate source tables before prefix rewriting; make existing-site overwrite explicit; fail on database errors.
- Tests covering the two command classes above — add ZIP/SQL fixtures for a main site plus at least two subsites.
Reference pattern
The importer currently maps a source database prefix to the target blog prefix before importing. Preserve that mapping only for the selected source blog's tables. Do not treat every table beginning with the network base prefix as belonging to the main site: that prefix also begins every subsite table name.
Implementation guidance
- Build an explicit source-table allowlist during export. For a main-site export, include main-site and supported per-site plugin tables, but exclude
base_prefix + <numeric_blog_id> + _* tables and network/global tables.
- Do not rely only on the default
wp db tables --scope=blog result when it omits custom per-site plugin tables. Define and test a classifier that preserves supported main-site custom tables while excluding other site prefixes.
- Store or derive the allowlist at import time and reject archives that contain unexpected site-prefixed tables.
- If
--blog_id targets an existing site, require an explicit overwrite flag. With that flag, replace only allowlisted target tables; otherwise fail before extraction or database work.
- Treat any SQL import error as a failed import. Do not emit success, delete queue state, or remove recovery artifacts after database errors.
- Keep fresh-target and ordinary subsite imports working unchanged.
Acceptance criteria
Verification
- Add unit or integration fixtures containing main-site, two-subsite, and network/global table names.
- Assert generated archive and transformed import SQL contain only allowlisted table names.
- Assert a simulated SQL failure returns non-zero and preserves recovery state.
- Run the relevant PHP test suite and static analysis.
Related work
Related to closed network-bundle work #1149 and #1150, but this is a regression/safety defect in the single-site main-site export/import path.
Summary
Main-site export archives can include tables belonging to other network sites. The importer then rewrites every source base-prefix table name, allowing unrelated source-site tables to be created under the target-site prefix. Existing-site imports can also emit database errors yet finish with a success message.
Evidence
prefix_3_*,prefix_4_*, and similar), not only source main-site tables.table already existserrors but reported successful completion.Files to modify
inc/site-exporter/mu-migration/includes/commands/class-mu-migration-export.php— derive the export table set from the requested blog only.inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php— validate source tables before prefix rewriting; make existing-site overwrite explicit; fail on database errors.Reference pattern
The importer currently maps a source database prefix to the target blog prefix before importing. Preserve that mapping only for the selected source blog's tables. Do not treat every table beginning with the network base prefix as belonging to the main site: that prefix also begins every subsite table name.
Implementation guidance
base_prefix + <numeric_blog_id> + _*tables and network/global tables.wp db tables --scope=blogresult when it omits custom per-site plugin tables. Define and test a classifier that preserves supported main-site custom tables while excluding other site prefixes.--blog_idtargets an existing site, require an explicit overwrite flag. With that flag, replace only allowlisted target tables; otherwise fail before extraction or database work.Acceptance criteria
Verification
Related work
Related to closed network-bundle work #1149 and #1150, but this is a regression/safety defect in the single-site main-site export/import path.