GRANT OPTION 会引发权限不可控扩散,用户可将其持有的所有权限(含隐式继承和后续新增)转授他人,且MySQL不校验其是否具备被授予权限;撤销仅能阻止新授权,无法收回已转授权限。

GRANT OPTION 会把权限转授变成不可控的扩散链
它不是“允许用户管理几个表”,而是让该用户能把自己当前持有的所有权限(包括隐式继承自角色的、甚至后续新增的)全部转授出去。比如你只给了 SELECT ON app_db.*,但用户用 GRANT SELECT ON *.* TO 'hacker'@'%' 就能把整个实例的读权限送出去——MySQL 不校验他有没有这个权限,只看他当前是否持有。
- 一旦误授,没有审计日志记录“谁把什么权限转给了谁”,
SHOW GRANTS FOR查不到下游授权痕迹 - 撤销时不能“收回已转授的权限”,只能阻止后续新授权:
REVOKE GRANT OPTION ON app_db.* FROM 'u'@'%'(MySQL 8.0.16+ 才支持) - 如果用户本身还绑定了角色,而角色里有
SUPER或FILE,那这些高危权限也会被一并转授
GRANT OPTION 和 WITH ADMIN OPTION 完全不是一回事
很多人以为给用户加个 WITH GRANT OPTION 就是“分级管理”,其实这是把两套机制混了。WITH GRANT OPTION 是账户级委托,WITH ADMIN OPTION 是角色级委托,且后者才是 MySQL 8.0 唯一可控的分级方案。
-
GRANT OPTION只能绑定到具体账户,不能绑定到角色;角色本身无法拥有该选项 -
WITH ADMIN OPTION必须配合CREATE ROLE使用,例如GRANT 'backup_admin' TO 'ops_lead'@'10.0.1.%' WITH ADMIN OPTION,此时 ops_lead 只能再授'backup_admin'这个角色,不能授其他任何权限 - 角色必须显式激活(
SET DEFAULT ROLE)或登录时指定(--default-authentication-plugin),否则权限不生效
root 账户报 “GRANT OPTION denied” 往往是因为认错了用户
你连的是 'root'@'192.168.1.100',但 mysql.user 表里只有 'root'@'localhost' 有 Grant_priv='Y',那远程连接就真的没授权能力——这不是权限没开,是压根没配对。
- 执行
SELECT USER(), CURRENT_USER();看清实际认证账户 - 检查对应
host行的Grant_priv字段是否为Y,不是就用UPDATE mysql.user SET Grant_priv='Y' WHERE user='root' AND host='192.168.1.100'; - 改完必须
FLUSH PRIVILEGES;,且要重新登录才生效
USAGE + GRANT OPTION 组合会导致意外可见性泄露
当用户对某个库只有 USAGE 权限却带 WITH GRANT OPTION,比如 GRANT USAGE ON `file`.* TO 'ttt'@'%' WITH GRANT OPTION,MySQL 会允许他看到这个库名,甚至可能通过元数据查询推导出更多结构信息——这不是 bug,是权限匹配逻辑决定的:只要某条 db 表记录命中,就会暴露对应数据库名。
- 这种组合常出现在自动化脚本误操作中,比如先
GRANT USAGE占位,再补WITH GRANT OPTION,结果忘了删掉无意义的USAGE -
SHOW DATABASES结果变多,往往就是这类残留权限在起作用 - 清理方式不是删库,而是精准
REVOKE USAGE ON `file`.* FROM 'ttt'@'%';,再FLUSH PRIVILEGES;
真正危险的从来不是“能不能做”,而是“做了之后没人知道、没法回滚、边界彻底消失”。GRANT OPTION 放在普通用户手上,就像把消防栓钥匙交给每层楼的租户——水压一上来,整栋楼都得跟着淹。


















