Repository navigation
Fixed - Security: SQLi in datagrid, image-ZIP import RCE, installer takeover + hardening (master) - #535
Conversation
…akeover + hardening - Validate locale/channel scope codes and escape JSON_EXTRACT path segments (SQLi, CWE-89) - Gate roles.store/roles.update/users.update mutator routes in ACL (authz bypass / priv-esc, CWE-862) - Per-entry image allowlist + MIME check on ZIP import extraction, preserve subfolders, zip-slip guard (stored XSS/RCE, CWE-434) - Persistent core_config install-completed flag + backfill migration; DB-populated guard on destructive install endpoints (unauth installer takeover, CWE-306) - Neutralize CSV/formula injection in export (skip numeric); throttle admin login; password min:8; remove forgot-password user enumeration
- orderByField: quote non-numeric ids instead of int-casting them (both grammars) so string-keyed ordering still works - isMarkedInstalled: drop the .env-file check so the DB install flag still seals containerized/env-var deployments without a .env on disk - isFormulaValue: also escape values whose first non-whitespace char is a formula char (e.g. leading-space '=SUM(...)') - image-ZIP import: default max entry size to 15MB so the size cap no longer rejects every image when unset - CategoryDataGridLocaleInjectionTest: make JSON-path assertions dialect-agnostic (fixes PostgreSQL Pest failure)
There was a problem hiding this comment.
Pull request overview
Ports a set of security hardening changes to master across Core query grammars, Admin datagrids/import flows, and the Installer to address SQL injection, unsafe ZIP image extraction, installer takeover, and spreadsheet formula injection, with regression coverage.
Changes:
- Add request-scope validation and SQL-escaping/quoting improvements in Core DB grammars (MySQL/Postgres) to mitigate SQLi vectors.
- Replace bulk ZIP extraction with safe, allowlisted, MIME-checked per-entry extraction (zip-slip + zip-bomb entry-size cap) for image ZIP imports.
- Add a persistent “installed” DB flag + backfill migration and use it to gate installer endpoints even if the storage marker is missing; add security-focused tests (Pest + Playwright).
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e-pw/tests/08-security/category-locale-sqli.spec.js | Playwright regression spec for locale-based SQLi in Category datagrid. |
| packages/Webkul/Installer/tests/Feature/InstallerSecurityTest.php | Adjust installer security tests to reset the new DB “installed” flag. |
| packages/Webkul/Installer/tests/Feature/InstallerDbStateGateTest.php | New feature tests ensuring destructive installer endpoints are blocked when DB indicates installed. |
| packages/Webkul/Installer/tests/Feature/InstallerControllerTest.php | Ensure installer controller tests clean up the persistent install flag. |
| packages/Webkul/Installer/src/Http/Middleware/CanInstall.php | Installer middleware now checks both storage marker and DB installed flag. |
| packages/Webkul/Installer/src/Http/Controllers/InstallerController.php | Add DB-populated guard and persist install flag when marking installed. |
| packages/Webkul/Installer/src/Helpers/DatabaseManager.php | Implement persistent installer.installed flag read/write helpers. |
| packages/Webkul/Installer/src/Console/Commands/Installer.php | CLI installer now persists the DB install flag as well. |
| packages/Webkul/DataTransfer/tests/Unit/Buffer/FileBufferFormulaInjectionTest.php | Unit tests for CSV/XLSX formula-injection neutralization. |
| packages/Webkul/DataTransfer/src/Providers/DataTransferServiceProvider.php | Register new image import config. |
| packages/Webkul/DataTransfer/src/Config/image_import.php | Configure max per-entry uncompressed size for image ZIP extraction. |
| packages/Webkul/DataTransfer/src/Buffer/FileBuffer.php | Escape formula-like string cells while preserving numeric values. |
| packages/Webkul/Core/tests/Unit/ScopeCodeInjectionTest.php | Unit tests for scope-code validation and JSON path escaping behavior. |
| packages/Webkul/Core/src/Helpers/Database/Grammars/PostgresGrammar.php | Escape JSON path segments; adjust orderByField handling for Postgres. |
| packages/Webkul/Core/src/Helpers/Database/Grammars/MySQLGrammar.php | Escape JSON path segments; adjust orderByField handling for MySQL. |
| packages/Webkul/Core/src/Database/Migrations/2026_07_01_000000_backfill_installer_installed_flag.php | Backfill migration to seal installer on already-installed DBs. |
| packages/Webkul/Core/src/Core.php | Validate request locale/channel scope codes before using in raw-SQL paths. |
| packages/Webkul/Admin/tests/Feature/DataTransfer/ImageZipImportSecurityTest.php | Feature tests for image ZIP allowlist, MIME validation, zip-slip, entry-size cap, and subfolder preservation. |
| packages/Webkul/Admin/tests/Feature/Catalog/CategoryDataGridLocaleInjectionTest.php | Feature tests ensuring datagrid SQL does not contain injected locale payloads. |
| packages/Webkul/Admin/tests/Feature/Auth/PasswordPolicyAndEnumerationTest.php | Feature tests for stronger password policy and no forgot-password enumeration. |
| packages/Webkul/Admin/tests/Feature/Auth/LoginThrottleTest.php | Feature test verifying admin login throttling. |
| packages/Webkul/Admin/tests/Feature/Acl/Settings/RoleUserAuthorizationTest.php | Feature tests ensuring role/user mutator routes are ACL-gated. |
| packages/Webkul/Admin/src/Http/Controllers/User/ResetPasswordController.php | Increase minimum admin reset password length. |
| packages/Webkul/Admin/src/Http/Controllers/Settings/DataTransfer/ImportController.php | Replace extractTo() with safe, per-entry image extraction. |
…ins, fix docblock - orderByField: revert to raw id list — the auto-quoting double-quoted callers that already pass quoted literals (AiAgent EditImage 'image'/'gallery'), breaking FIELD ordering. Callers pass integer ids or pre-quoted literals, never raw user input. - jsonContains: escape JSON path segments (parity with jsonExtract) so dynamic segments can't break out of the quoted literal. - CanInstall::isInstallationCompleted docblock: reflect that it now also checks the persistent DB install flag, not just the storage marker. - Add grammar regression tests.
|
Addressed the round-2 review comments:
|
…(review feedback)
|
Follow-up on the ZIP in-memory read: lowered the default |
…akeover + hardening (master) (unopim#535) * Fixed - Security: SQLi in datagrid, image-ZIP import RCE, installer takeover + hardening - Validate locale/channel scope codes and escape JSON_EXTRACT path segments (SQLi, CWE-89) - Gate roles.store/roles.update/users.update mutator routes in ACL (authz bypass / priv-esc, CWE-862) - Per-entry image allowlist + MIME check on ZIP import extraction, preserve subfolders, zip-slip guard (stored XSS/RCE, CWE-434) - Persistent core_config install-completed flag + backfill migration; DB-populated guard on destructive install endpoints (unauth installer takeover, CWE-306) - Neutralize CSV/formula injection in export (skip numeric); throttle admin login; password min:8; remove forgot-password user enumeration * Cap image-ZIP entry size to prevent memory-exhaustion DoS * Address review feedback and fix PostgreSQL CI - orderByField: quote non-numeric ids instead of int-casting them (both grammars) so string-keyed ordering still works - isMarkedInstalled: drop the .env-file check so the DB install flag still seals containerized/env-var deployments without a .env on disk - isFormulaValue: also escape values whose first non-whitespace char is a formula char (e.g. leading-space '=SUM(...)') - image-ZIP import: default max entry size to 15MB so the size cap no longer rejects every image when unset - CategoryDataGridLocaleInjectionTest: make JSON-path assertions dialect-agnostic (fixes PostgreSQL Pest failure) * Address review round 2: revert orderByField quoting, escape jsonContains, fix docblock - orderByField: revert to raw id list — the auto-quoting double-quoted callers that already pass quoted literals (AiAgent EditImage 'image'/'gallery'), breaking FIELD ordering. Callers pass integer ids or pre-quoted literals, never raw user input. - jsonContains: escape JSON path segments (parity with jsonExtract) so dynamic segments can't break out of the quoted literal. - CanInstall::isInstallationCompleted docblock: reflect that it now also checks the persistent DB install flag, not just the storage marker. - Add grammar regression tests. * Lower image-import per-entry size cap to 15MB to bound import memory (review feedback)
Issue Reference
Security fixes ported to
master(companion to #533 [2.0, merged] and #534 [2.1]): SQL injection (CWE-89), image-ZIP import RCE/stored-XSS (CWE-434), unauthenticated installer takeover (CWE-306), CSV/XLSX formula injection.Description
locale/channelscope codes; escapejsonExtract/jsonContainsJSON-path segments (MySQL + Postgres); quote non-numeric ids inorderByField.extractImageEntrieskeeps only allowlisted image extensions with a real-MIME check, preserves subfolders, blocks zip-slip, and caps each entry's uncompressed size (default 15 MB) against zip bombs.core_configinstall-completed flag (survives loss of thestorage/installedmarker) + backfill migration for already-installed instances; DB-populated guard on the destructive migration/seeder endpoints.Incorporates the Copilot review feedback from #534 (orderByField quoting,
.env-independent install flag, whitespace-aware formula check, ZIP-bomb size cap) and the PostgreSQL-portable datagrid assertions.How To Test This?
Green locally: security suites + 166 Core/DataGrid/Product tests.
vendor/bin/pint --testclean.Documentation
Branch Selection
Pint
Passed.
Tailwind Reordering
N/A.