Repository navigation
fix(site): restrict each site's database grant to its own database - #512
Merged
mrrobot47 merged 6 commits intoOct 12, 2026
Merged
Conversation
…limit Escaping every `_`, `%` and `\` in the grant's database name can make it longer than 64 characters. MariaDB 10.11 then stores the name cut short, so the grant no longer covers the site's database, and MariaDB 12 rejects the GRANT. Escape as many pattern characters as fit and let `_` stand for each remaining one, which still matches it. The quoting moves to sql_quote_grant_database() so the upgrade migration can use the same grant name.
…base Sites on the global database created before the grant escaped `_` and `%` still hold a grant whose database name is a pattern, and a long escaped name may have been stored cut to 64 characters. A container migration adds the current grant for each such site, then revokes the old one only if it exists, so it is safe to run again. Local and remote database sites are skipped. A site whose grant can't be read or changed gets a warning with the SQL to run, and the upgrade continues. down() keeps the new grant.
A default database name is now cut so that its escaped grant name fits in 64 characters, and a suffixed default name respects the same limit, so a new site's grant covers exactly its own database. An explicit --dbname that is too long for that still works through the partial escape, with a warning at create time.
…n the grant migration The migration now only rewrites old grant rows that are exactly the ALL PRIVILEGES grant EasyEngine creates, checked against the privilege columns the server reports. A grant that was changed by hand, a grant that another site of the same database user relies on, and a user that exists only for other hosts are reported with a warning naming the site instead. Sites whose database name is too long for an exact grant get a warning too. The grants of all sites are read in one round trip, and a stopped or unreadable global database gives a single warning with SQL only for the sites it applies to.
reserve_global_db_names() refuses names longer than 64 bytes, so the default name is now also cut on a character boundary to fit 64 bytes, not only 64 characters. The create-time warning for a long explicit --dbname now says the grant may match other names of the same length.
…manual SQL safe Privilege columns added after MariaDB 10.2 are set to 'N' on existing rows when mariadb-upgrade adds them, so the migration now requires 'Y' only on the 10.2 privilege columns (and 'N' on Grant_priv) when it decides whether a row is the grant EasyEngine created. When the global database is stopped or its grants can't be read, the warning now states when the SQL applies, gives one statement per line and the command to open a root shell, and lists sites that share a database user with only the GRANT. The not-exact warning now says the grant may still match other names of the same length.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The offline fallback omits truncated legacy grants, potentially leaving unintended database access.
1 open finding
What changed in this PR
Restricts global database users to their sites’ databases and safely sizes new database names for exact grants.
Changes:
- Adds grant-aware database-name quoting and truncation.
- Migrates existing legacy wildcard grants to restricted grants.
- Provides warnings and manual SQL when automatic migration is unsafe.
| File | Description |
|---|---|
src/helper/site-utils.php |
Adds safe grant quoting and database-name sizing. |
migrations/container/20260930120000_site-command_restrict_global_db_grants.php |
Migrates legacy global database grants. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

On the global database,
_and%in a database-level GRANT are wildcards even inside backticks. New sites have had their grant escaped since v4.13.1. This adds a container migration that does the same for existing sites: for each site on the global database, it adds a grant on the site's exact database name and then removes the old pattern grant. The site keeps access throughout.%host are left as they are, with a warning naming the site.down()is a no-op (re-granting the pattern would widen access again).It also keeps the escaped grant name within MariaDB's 64-character limit: default database names for very long domains are shortened so the grant always fits (on v4.13.1 such sites could not be created).
Tested end to end against MariaDB 10.11 and 12.3 on PHP 7.4 and 8.5, with PHPUnit, and live on a test server.