Make Script helper work in strict FIPS mode by avoiding client-side SHA-1#3700
Conversation
|
Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset. In case there are security findings, they will be communicated to you as a comment inside the PR. Hope you’ll enjoy using Jit. Questions? Comments? Want to learn more? Get in touch with us. |
|
@chaitanyabodlapati thank you for opening this pr. I am no a fan of using init here. Would prefer the application to control this with an option. What do you think? |
|
Thanks for the feedback — that makes sense. |
|
@chaitanyabodlapati If you are shipping the client as a prebuilt binary I would suggest to do a wrapper or a patch on your end. Such environment variables make sense in tests and applications, rarely in libraries and only for such that are specifically made to run in a given setup. Let's discuss another way to facilitate this. Explicit option would be a breaking change. Let me see if I understand your usecase correctly:
|
|
Thanks, that’s a fair point — let me give a bit more context on our use case. We ship Traefik (which uses go-redis v9) as part of a bigger product as a single prebuilt binary. Our customers do not write Go code or construct In strict FIPS environments we run with What we would like is a way to use server-side SHA for scripts when we are in FIPS mode, without changing the behavior for everyone else: Non-FIPS: keep current behavior ( We understand your concerns about keep On our side, we can then do the runtime decision in Traefik: non-FIPS: call That way the library stays clean (no env vars, no Would that approach work for you? If yes, I can update the PR to drop the env-based toggle and instead implement the separate “server-SHA” constructor. |
|
Funny enough, we at @CampusTech are suddenly in need of a FIPS-140 compliant Redis library too (and must run |
|
@chaitanyabodlapati this additional method that will directly use Server for hashing is the correct approach for a library in my mind. Feel free to implement it. This will provide the tools to the application to decide how to create the |
…SHA-1 Behaviour(strict FIPS Builds - FIPS140)
|
Thanks for the feedback . |
ndyakov
left a comment
There was a problem hiding this comment.
looks good, would you mind adding some unit and integration tests and I can merge.
ndyakov
left a comment
There was a problem hiding this comment.
Please drop the miniredis dependency, the rest looks OK. Feel free to use the redis that works on the default port in the CI for your tests.
There was a problem hiding this comment.
left the required changes as suggestions
i was planning to address this, since my review was what delayed the merge of this PR, but the maintainer_can_modify is false, so @chaitanyabodlapati, feel free to address this and ping me when it is done.
|
@chaitanyabodlapati thanks for pushing the fix 🙌 i’m seeing the same issue on my side and noticed a few subtle concerns in the PR:
TLDR: |
|
@panga 1) and 2) sound like application logic, not client logic. In my opinion, since this is achievable with what the client provides it can be implemented in the application. 3) is something that can be addressed by getting a specific node client with |
|
My point on 3) is that This avoids introducing custom coordination logic and eliminates an additional Redis round-trip. |
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
Moved the dependency under require block
@ndyakov This PR is coming from a fork, so I don't have the ability to enable "maintainer can modify" on my side. |
ndyakov
left a comment
There was a problem hiding this comment.
Thank you @chaitanyabodlapati , this looks good for now. After reading some more on the topic I do think for v10 we can incorporate the debug env as well, but let's keep it as in this PR for now.
|
@ndyakov I noticed my comment about cluster mode doesn’t seem to have been addressed in the merged code. Is this something you plan to look at before releasing? |
|
@panga feel free to submit an issue. It is a known problem for the team but with lower priority compared to other work we are doing at this time. If someone from the community would like to take a shot at it that would be great. |
go-redis
Scriptcurrently computes the script digest using SHA-1 inNewScript()and then uses that digest forEVALSHA.In strict FIPS environments, client-side SHA-1 can be blocked, which causes applications using
Script/EVALSHAto fail.This PR adds a FIPS-safe path where go-redis does not compute SHA-1 in Go:
--> Default behavior is unchanged for existing users: we still compute the digest locally and use
EVALSHA.--> In FIPS mode, we obtain the digest from Redis instead:
--> call
SCRIPT LOADto load the script--> Redis returns the script digest
--> cache the returned digest in the
Scriptobject--> use that digest for
EVALSHA/EVALSHA_RO--> If Redis returns
NOSCRIPT(script cache flushed), we reload once and retry.--> If loading fails, we fall back to
EVAL/EVALROto avoid hard failures.FIPS mode is enabled when either:
-->
GODEBUGincludesfips140=onlyorfips140=on, or-->
GO_REDIS_DISABLE_CLIENT_SHA1=trueis set (manual override).This keeps the common path identical, while allowing strict FIPS deployments to use scripts without client-side SHA-1.
Note
Medium Risk
Adds a new execution path for Redis scripts that changes how
Scripthashes are populated/cached and introduces retry logic onNOSCRIPT; while mostly opt-in viaNewScriptServerSHA, it touches frequently used script helpers and adds locking that could affect concurrency behavior.Overview
Adds an opt-in
NewScriptServerSHAmode forScriptthat avoids client-side SHA-1 by usingSCRIPT LOADto obtain and cache the digest, then running viaEVALSHA/EVALSHA_RO.Updates
Scriptto be concurrency-safe (mutex-protected hash) and to reload+retry once onNOSCRIPTfor the server-hash path, with fallback toEVAL/EVALROifSCRIPT LOADfails;Loadnow also caches the returned digest.Adds unit + integration tests covering digest caching and
SCRIPT FLUSH/NOSCRIPTretry behavior, and tidiesgo.modby movinggo.uber.org/atomicinto the mainrequireblock.Written by Cursor Bugbot for commit 36f2731. This will update automatically on new commits. Configure here.