Redis 6.0 ACL 不支持对 EVAL/EVALSHA 细粒度控制,因 Lua 脚本内 redis.call 调用不经过 ACL 检查;可控边界仅限是否允许执行 Lua,需通过禁用命令、代理白名单、审计日志或升级至 Redis 7.0+ Functions 实现权限收敛。

Redis 6.0 的 ACL 机制本身**不支持对 EVAL、EVALSHA 等 Lua 执行命令做细粒度权限隔离**——你无法通过 ACL SETUSER 直接限制“只允许运行某个 SHA1 的脚本”或“只允许读取 key_a 但不能写 key_b”的 Lua 行为。
为什么 ACL 无法限制 Lua 脚本的具体行为?
ACL 控制的是客户端可执行的 Redis 命令,而 Lua 脚本在服务端以原子方式执行,其内部调用的 redis.call("GET", "x") 或 redis.call("SET", "y", "z") 不经过 ACL 检查。一旦用户有 EVAL 权限,脚本内就能任意操作所有 key(除非被 rename-command 屏蔽)。
- ACL 规则只校验顶层命令,比如
EVAL、GET,不穿透到 Lua 运行时 - 即使给用户分配
on +get +hget,只要他有+eval,就能在脚本里调用redis.call("set", ...) - Redis 不提供类似 “script allowlist” 或 “sandboxed Lua env” 的内置机制
实际可行的权限收敛方案
绕过 ACL 的局限,需组合使用配置项与运行时约束:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 禁用高危命令:在
redis.conf中重命名或禁用EVAL和EVALSHA,例如rename-command EVAL "",再通过代理层或白名单 SHA 提供受限执行入口 - 启用
lua-time-limit(默认 5000ms)防止无限循环,但注意超时会引发BUSY错误,需客户端配合重试或降级 - 使用
ACL LOG记录所有带+eval权限用户的调用,配合外部审计工具识别异常模式(如高频调用、访问非预期 key 前缀) - 若业务允许,改用
FUNCTION LOAD(Redis 7.0+)替代 Lua,因其支持更严格的函数级 ACL(但 6.0 不支持)
典型错误配置及后果
常见误操作是以为设置 ACL SETUSER alice on >p123 +get ~user:* +eval 就能安全运行脚本,结果发现:
-
alice可执行EVAL "return redis.call('DEL', KEYS[1])" 1 secret_key—— 删除任意 key,哪怕 ACL 没给+del - 脚本中调用
redis.call("CONFIG", "GET", "maxmemory")会失败(CONFIG默认被禁用),但这是命令禁用所致,不是 ACL 限制 - 若忘记关闭
lua-time-limit或设得过大,恶意脚本可能拖垮整个实例
真正可控的边界在「是否允许执行 Lua」这一层,而非「Lua 能做什么」——后者必须靠代码审查、沙箱代理或升级到 Redis 7.0+ 的 Functions + ACL 组合来解决。

















