hush/vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md
jx12n 4d9a26498e hush: one-time secret links the server cannot read
Paste a secret, get a link, send it. The first person to open it and press
Reveal sees the secret; the link dies at that moment. The recipient needs a
browser and nothing else — no account, no client, no installed tooling.

The server cannot read what it stores. AES-256-GCM happens in the browser and
the key lives in the URL fragment, which browsers never transmit, so hushd
holds ciphertext and no key material. That is a property of where the key sits
rather than a promise about our conduct, which is why there is deliberately no
endpoint accepting a plaintext secret and no server-side-encryption fallback:
two guarantees behind one URL would be worse than one honest guarantee.

Three decisions carry the design:

  * GET /s/{id} touches NO storage, not even to check existence. Slack, Teams,
    WhatsApp, iMessage and Outlook Safe Links all fetch a URL before a human
    sees it, so destroying on GET would destroy most secrets in transit and the
    recipient's "already used" would be indistinguishable from interception.
    Only POST /reveal consumes. Bot user-agent detection is an arms race;
    removing the side effect from GET is not. Pinned by
    TestGettingTheRevealPageNeverConsumesTheSecret.
  * Destruction is one Redis GETDEL, which is atomic. GET-then-DEL has a window
    where two simultaneous readers both win, and for a one-time secret that
    window is the product. The store contract demands atomicity and the same
    concurrency test runs against both implementations.
  * Missing, already-revealed, expired and evicted are ONE indistinguishable
    410. Separating them would confirm to a prober that a given link was real.

The secret id IS the capability, so secret.ID is a struct whose every
accidental path — %v, %s, String(), slog, json.Marshal — emits a redacted
handle or refuses, and the raw value needs an explicit Value(). The first
version tried to prevent leaks by implementing no String() at all; its own test
caught that Go's fmt prints unexported fields anyway, so forbidding the method
had removed the control rather than the leak.

Operationally: structured JSON on stdout in the fleet's wire format, which
Vector already collects with no annotation; six hush_* metrics on the chassis
registry with no id, IP or path in any label; five alert rules wired into
vmalert. The public Ingress enumerates /, /s/ and /api/ so /metrics, /healthz
and /readyz share the port but are unreachable from the internet — no
basic-auth middleware to maintain and get wrong.

Dependencies are vendored because go-chassis is private: the Woodpecker test
step and the in-cluster Kaniko build both run -mod=vendor with GOPROXY=off and
hold no git credential.

cmd/hush-mcp is a stdio MCP server doing the same client-side crypto locally,
so using hush from an agent preserves the same guarantee as using it from a
browser.
2026-09-03 00:08:38 -06:00

4.3 KiB

Contributing

Introduction

We appreciate your interest in considering contributing to go-redis. Community contributions mean a lot to us.

Contributions we need

You may already know how you'd like to contribute, whether it's a fix for a bug you encountered, or a new feature your team wants to use.

If you don't know where to start, consider improving documentation, bug triaging, and writing tutorials are all examples of helpful contributions that mean less work for you.

Your First Contribution

Unsure where to begin contributing? You can start by looking through help-wanted issues.

Never contributed to open source before? Here are a couple of friendly tutorials:

Getting Started

Here's how to get started with your code contribution:

  1. Create your own fork of go-redis
  2. Do the changes in your fork
  3. If you need a development environment, run make docker.start.

Note: this clones and builds the docker containers specified in docker-compose.yml, to understand more about the infrastructure that will be started you can check the docker-compose.yml. You also have the possiblity to specify the redis image that will be pulled with the env variable CLIENT_LIBS_TEST_IMAGE. By default the docker image that will be pulled and started is redislabs/client-libs-test:8.10.0. If you want to test with newer Redis version, using a newer version of redislabs/client-libs-test should work out of the box.

  1. While developing, make sure the tests pass by running make test (if you have the docker containers running, make test.ci may be sufficient).

Note: make test will try to start all containers, run the tests with make test.ci and then stop all containers.

  1. If you like the change and think the project could use it, send a pull request

To see what else is part of the automation, run invoke -l

Testing

Setting up Docker

To run the tests, you need to have Docker installed and running. If you are using a host OS that does not support docker host networks out of the box (e.g. Windows, OSX), you need to set up a docker desktop and enable docker host networks.

Running tests

Call make test to run all tests.

Continuous Integration uses these same wrappers to run all of these tests against multiple versions of redis. Feel free to test your changes against all the go versions supported, as declared by the build.yml file.

Troubleshooting

If you get any errors when running make test, make sure that you are using supported versions of Docker and go.

How to Report a Bug

Security Vulnerabilities

NOTE: If you find a security vulnerability, do NOT open an issue. Email Redis Open Source (oss@redis.com) instead.

In order to determine whether you are dealing with a security issue, ask yourself these two questions:

  • Can I access something that's not mine, or something I shouldn't have access to?
  • Can I disable something for other people?

If the answer to either of those two questions are yes, then you're probably dealing with a security issue. Note that even if you answer no to both questions, you may still be dealing with a security issue, so if you're unsure, just email us.

Everything Else

When filing an issue, make sure to answer these five questions:

  1. What version of go-redis are you using?
  2. What version of redis are you using?
  3. What did you do?
  4. What did you expect to see?
  5. What did you see instead?

Suggest a feature or enhancement

If you'd like to contribute a new feature, make sure you check our issue list to see if someone has already proposed it. Work may already be underway on the feature you want or we may have rejected a feature like it already.

If you don't see anything, open a new issue that describes the feature you would like and how it should work.

Code review process

The core team regularly looks at pull requests. We will provide feedback as soon as possible. After receiving our feedback, please respond within two weeks. After that time, we may close your PR if it isn't showing any activity.

Support

Maintainers can provide limited support to contributors on discord: https://discord.gg/W4txy5AeKM