Repository navigation
fix(client): retry a read-only script with EVAL_RO after NOSCRIPT - #3567
nkaradzhov merged 1 commit into
Conversation
A script defined with IS_READ_ONLY is sent as EVALSHA_RO, but when the server answers NOSCRIPT the retry is plain EVAL, and MULTI always queues EVAL/EVALSHA for it. A user allowed only EVAL_RO and EVALSHA_RO gets NOPERM on every call, and the script is never loaded. Use EVAL_RO for the NOSCRIPT retry of a read-only script, and EVAL_RO/EVALSHA_RO for it in MULTI, the same choice scriptArgumentsPrefix already makes for EVALSHA_RO.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Thanks @maxymlyskov for the focused read-only The new regression cases in this PR establish read-only command routing but grant key access via This is not an alternative implementation fix and is intended to complement the original author's tests. The single-file source is provided below for review. Would you prefer a small follow-up test-only PR, or folding the additional ACL assertion into #3567? Happy to follow the maintainers' preferred placement. Proposed native regression test:
|
Description
Fixes #3563
A script defined with
IS_READ_ONLY: truegoes out asEVALSHA_RO, but when the server answers NOSCRIPT,_executeScriptretries with plainEVAL. Andmulti().addScript()always queuesEVAL/EVALSHAfor it. So a user whose ACL allows onlyEVAL_ROandEVALSHA_ROgets NOPERM on every call, and the script never gets loaded.With the repro from the issue (an ACL user with
+eval_ro +evalsha_roand no+eval, afterSCRIPT FLUSH), master against Redis 8.10.2 fails every call, direct and in MULTI, withNOPERM User ro-user has no permissions to run the 'eval' command. With this branch both return the value.The retry now uses
EVAL_ROfor a read-only script, and MULTI usesEVAL_RO/EVALSHA_RO, the same choicescriptArgumentsPrefixalready makes. Note: a script marked read-only that writes used to get through on its first call and in MULTI. Now the server rejects it every time, as it already did from the second call on.Added tests for the direct and MULTI paths with a read-only ACL user, plus the args case in
multi-command.spec.ts. They fail on master.npm testpasses except one sentinel case,destroy() from an end listener tears down a reentrant reopen. It passes 5 times out of 5 alone and has failed on master here before. tsc and eslint are clean.Checklist
npm testpass with this change (including linting)?Note
Medium Risk
Touches script execution and ACL-sensitive command choice on NOSCRIPT retry and MULTI; behavior change for mislabeled read-only scripts that write.
Overview
Fixes #3563: scripts with
IS_READ_ONLY: truealready went out asEVALSHA_ROon the first call, but NOSCRIPT recovery retried with plainEVAL, andmulti().addScript()always queuedEVAL/EVALSHA. ACL users allowed onlyeval_ro/evalsha_rohit NOPERM afterSCRIPT FLUSH(or on the first load in MULTI) and could not run those scripts._executeScriptnow retries withEVAL_ROwhen the script is read-only.RedisMultiCommand.addScriptpicksEVAL_RO/EVALSHA_ROthe same wayscriptArgumentsPrefixdoes for direct calls.Integration tests exercise an ACL user without
eval/evalshaafter flush; a unit test asserts MULTI queue args. Behavior change: a script marked read-only that actually writes is rejected consistently by the server (including the first call and MULTI), not only after the SHA is cached.Reviewed by Cursor Bugbot for commit 5eadd19. Bugbot is set up for automated code reviews on this repo. Configure here.