From 3328d7cf1909978c4391496d257ca0a36aa29c57 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 21 Jun 2026 18:50:07 -0500 Subject: [PATCH 1/2] feat: backup type filter + path traversal protection (#68, #72) #68: Add backup type filter dropdown to backups list view - filter_backups.xml: full/database/files/differential options - BackupsModel: backup_type filter in getListQuery() - Language string: COM_MOKOJOOMBACKUP_FILTER_TYPE_ALL #72: Path traversal protection in RestoreEngine and MokoRestore - RestoreEngine::extractArchive(): validate ZIP entries before extractTo() - RestoreEngine::extractTarGz(): validate PharData entries before extractTo() - MokoRestore standalone script: same validation in generated PHP code - Rejects entries containing ../ or starting with / or \ Closes #68, closes #72 --- .../forms/filter_backups.xml | 12 +++++++++ .../language/en-GB/com_mokosuitebackup.ini | 1 + .../src/Engine/MokoRestore.php | 14 ++++++++++ .../src/Engine/RestoreEngine.php | 26 +++++++++++++++++++ .../src/Model/BackupsModel.php | 7 +++++ 5 files changed, 60 insertions(+) diff --git a/source/packages/com_mokosuitebackup/forms/filter_backups.xml b/source/packages/com_mokosuitebackup/forms/filter_backups.xml index 11af4cc..a44abd5 100644 --- a/source/packages/com_mokosuitebackup/forms/filter_backups.xml +++ b/source/packages/com_mokosuitebackup/forms/filter_backups.xml @@ -19,6 +19,18 @@ + + + + + + + diff --git a/source/packages/com_mokosuitebackup/language/en-GB/com_mokosuitebackup.ini b/source/packages/com_mokosuitebackup/language/en-GB/com_mokosuitebackup.ini index 72366dd..bf9735b 100644 --- a/source/packages/com_mokosuitebackup/language/en-GB/com_mokosuitebackup.ini +++ b/source/packages/com_mokosuitebackup/language/en-GB/com_mokosuitebackup.ini @@ -167,6 +167,7 @@ COM_MOKOJOOMBACKUP_STATUS_PENDING="Pending" COM_MOKOJOOMBACKUP_FILTER_SEARCH="Search" COM_MOKOJOOMBACKUP_FILTER_STATUS="Status" COM_MOKOJOOMBACKUP_FILTER_STATUS_ALL="- Select Status -" +COM_MOKOJOOMBACKUP_FILTER_TYPE_ALL="- Select Type -" ; Tabs and fieldsets COM_MOKOJOOMBACKUP_TAB_GENERAL="General" diff --git a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php index 4c2f63f..06254ed 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php +++ b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php @@ -303,6 +303,20 @@ function actionExtract(array $data): array $zip->setPassword($password); } + // Validate all entries before extraction (path traversal protection) + for ($i = 0; $i < $zip->numFiles; $i++) { + $entryName = $zip->getNameIndex($i); + + if ($entryName === false) { + continue; + } + + if (str_contains($entryName, '../') || str_contains($entryName, '..\\') || str_starts_with($entryName, '/') || str_starts_with($entryName, '\\')) { + $zip->close(); + throw new RuntimeException('Archive contains unsafe path: ' . $entryName); + } + } + if (!$zip->extractTo(RESTORE_DIR)) { $zip->close(); throw new RuntimeException( diff --git a/source/packages/com_mokosuitebackup/src/Engine/RestoreEngine.php b/source/packages/com_mokosuitebackup/src/Engine/RestoreEngine.php index c95ae67..7ffd2b6 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/RestoreEngine.php +++ b/source/packages/com_mokosuitebackup/src/Engine/RestoreEngine.php @@ -191,6 +191,20 @@ class RestoreEngine $this->log('Decryption password set'); } + // Validate all entries before extraction (path traversal protection) + for ($i = 0; $i < $zip->numFiles; $i++) { + $entryName = $zip->getNameIndex($i); + + if ($entryName === false) { + continue; + } + + if (str_contains($entryName, '../') || str_contains($entryName, '..\\') || str_starts_with($entryName, '/') || str_starts_with($entryName, '\\')) { + $zip->close(); + throw new \RuntimeException('Archive contains unsafe path: ' . $entryName); + } + } + if (!$zip->extractTo($this->stagingDir)) { $zip->close(); @@ -210,6 +224,18 @@ class RestoreEngine private function extractTarGz(string $archivePath): void { $phar = new \PharData($archivePath); + + // Validate all entries before extraction (path traversal protection) + foreach (new \RecursiveIteratorIterator($phar) as $entry) { + $entryName = $entry->getPathname(); + // PharData paths are prefixed with phar:// — extract the relative part + $relative = substr($entryName, strlen('phar://' . $archivePath) + 1); + + if (str_contains($relative, '../') || str_contains($relative, '..\\') || str_starts_with($relative, '/') || str_starts_with($relative, '\\')) { + throw new \RuntimeException('Archive contains unsafe path: ' . $relative); + } + } + $phar->extractTo($this->stagingDir, null, true); $this->log('Extracted tar.gz archive'); } diff --git a/source/packages/com_mokosuitebackup/src/Model/BackupsModel.php b/source/packages/com_mokosuitebackup/src/Model/BackupsModel.php index c7466d3..d3290ad 100644 --- a/source/packages/com_mokosuitebackup/src/Model/BackupsModel.php +++ b/source/packages/com_mokosuitebackup/src/Model/BackupsModel.php @@ -61,6 +61,13 @@ class BackupsModel extends ListModel $query->where($db->quoteName('a.profile_id') . ' = ' . (int) $profileId); } + // Filter by backup type + $backupType = $this->getState('filter.backup_type'); + + if (!empty($backupType)) { + $query->where($db->quoteName('a.backup_type') . ' = ' . $db->quote($backupType)); + } + // Filter by search $search = $this->getState('filter.search'); -- 2.52.0 From 07e1d5475ea83478b5f516b3ee15344a09d67ad0 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 21 Jun 2026 23:50:32 +0000 Subject: [PATCH 2/2] chore(version): pre-release bump to 01.27.08-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- README.md | 2 +- mokosuitebackup.xml | 2 +- source/packages/com_mokosuitebackup/mokosuitebackup.xml | 2 +- .../packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml | 2 +- source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml | 2 +- source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml | 2 +- .../packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml | 2 +- source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml | 2 +- source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml | 2 +- .../plg_webservices_mokosuitebackup/mokosuitebackup.xml | 2 +- source/pkg_mokosuitebackup.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index ef92778..e9fdc13 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.27.03 +# VERSION: 01.27.08 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/README.md b/README.md index 29eb987..dacdfe6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MokoSuiteBackup - + Full-site backup and restore for Joomla — database, files, and configuration. diff --git a/mokosuitebackup.xml b/mokosuitebackup.xml index 962b0f7..278deaa 100644 --- a/mokosuitebackup.xml +++ b/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Web Services - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/com_mokosuitebackup/mokosuitebackup.xml b/source/packages/com_mokosuitebackup/mokosuitebackup.xml index 4ca9fc9..a5ee097 100644 --- a/source/packages/com_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/com_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml index 04fb991..0bf9de2 100644 --- a/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Action Log - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml index 634c9a1..70d7600 100644 --- a/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Console - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml index 18123a2..7fd3587 100644 --- a/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Content - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml index bb9946b..c2e0059 100644 --- a/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml @@ -1,7 +1,7 @@ Quick Icon - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml index aedc2e1..cb952de 100644 --- a/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> System - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml index 81bb64e..d201ea6 100644 --- a/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Task - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml index 962b0f7..278deaa 100644 --- a/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Web Services - MokoSuiteBackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/pkg_mokosuitebackup.xml b/source/pkg_mokosuitebackup.xml index 6906680..dcdda90 100644 --- a/source/pkg_mokosuitebackup.xml +++ b/source/pkg_mokosuitebackup.xml @@ -8,7 +8,7 @@ Package - MokoSuiteBackup mokosuitebackup - 01.27.03 + 01.27.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech -- 2.52.0