Repository navigation
Conversation
741e9b5 to
d4456f4
Compare
freshtonic
left a comment
There was a problem hiding this comment.
Reviewed head f7df5137 against release/2.2 (5f99d7e0, which includes #493 and #495). Approved. The version bump, the CHANGELOG section and the latest=false change are correct, and the dependency updates remove 10 of the 29 advisories that cargo audit reports on the base.
I pushed the fixes for S1 and S2 to this branch as two signed commits:
e66691acfix(deps): backport rustls 0.23.45 to 2.2. This is a 2-line change toCargo.lock. The CHANGELOG entry now namesrustlsandaws-lc-rs/aws-lc-sys, and it no longer says that 2.2.5 has every fix that 3.x ships.cargo build --workspace --all-targets --lockedpasses, andcargo test -p cipherstash-proxy -p eql-mapper --libpasses (283 and 79). RUSTSEC-2026-0285 is gone. The rustls advisories that remain are the same as onmain.103e7a86ci: remove the Multitudes deployment notification (2.2). This is the same change as #477 onmain.
This approval covers my two commits too. Please check them before you merge.
Fixed in this PR (S1 and S2)
S1. The rustls fix that main ships is not in this backport. release/2.2 locks rustls 0.23.28, which has RUSTSEC-2026-0285 ("TLS 1.3 handshake messages incorrectly accepted across encryption levels", network, no authentication). main locks 0.23.45, which fixes it. rustls is Proxy's TLS server for clients and its TLS client to PostgreSQL, so this is the most relevant advisory that remains. cargo update -p rustls --precise 0.23.45 changes only 2 lines in Cargo.lock. I built it, and the unit tests pass.
The CHANGELOG says that the update picks up "the fixes for published security advisories in those crates that Proxy 3.x already ships". That is true for the crates it names. But a reader can think that 2.2.5 has every fix that 3.x has, and it does not. Add rustls, or say which advisories stay open.
S2. The release run for v2.2.5 will end red. release.yml on 2.2 still has the "Notify Multitudes" step. #477 removed this step from main, because the endpoint has returned 500 on every run since 2026-08-17. The images are pushed before that step, so the release is published, but the run shows as failed, and the failure hides a real failure. Remove the step here too, as #477 did.
Notes (not blocking)
- postgres-protocol 0.6.8 has RUSTSEC-2026-0179 (a malicious server can send an unbounded SCRAM iteration count) and RUSTSEC-2026-0180.
maindoes not have these.cargo update -p postgres-protocol --precise 0.6.12resolves on 2.2, and it builds and passes the unit tests. It addsmd-50.11 andsha20.11 beside the existing versions. The server is the operator's own PostgreSQL, so the risk is low. You can add it with S1 or later. - tokio-postgres 0.7.13 has RUSTSEC-2026-0178 (panic on a short
DataRow).mainhas 0.7.18 (#465), but on 2.2,--precise 0.7.18fails on alibredoxconflict throughcipherstash-clientin the integration package. It is not worth blocking the release for this. A ticket for 2.2.6 is enough. - The lockfile update goes further than the CHANGELOG says.
aws-lc-sysmoves from 0.38.0 to 0.46.0, which is newer thanmain(0.44.0), andaws-lc-rsfrom 1.16.1 to 1.18.2. This fixes RUSTSEC-2026-0044 and RUSTSEC-2026-0048, so it is good. But it is a large update of the C crypto library, and it is not in the CHANGELOG. Test CI builds only x86_64. The release also buildsaarch64-unknown-linux-gnu, and that build has not run on this lockfile. Before you tag, start the Release workflow on this branch withworkflow_dispatch. The merge job is a dry run there, but the build job pushes untagged digests. - The advisories that remain and that
mainalso has (quinn-proto, h2, crossbeam-epoch, rkyv, the other rustls ones, rustls-webpki 0.103.14, webpki-root-certs) are not a 2.2 problem.
Nits
- The CHANGELOG date is
2026-10-26. Update it if the tag goes out on another day.
What I checked and found correct
- Version. The workspace version is
2.2.5, andcipherstash-proxy,eql-mapper-macrosandshowcaseare2.2.5inCargo.lock.verify-releasereads the firstversion =line ofCargo.tomland looks for## [2.2.5]in the CHANGELOG. Both match. latest=false. Areleaseevent runs the workflow file from the tag, so the 2.2release.ymlis used. The merge step makes:2.2.5({{version}}) and:2.2({{major}}.{{minor}}), and not:latest. On the build step the flavor changes only labels, so it does no harm. GitHub's "Latest" isv3.0.1now, and--latest=falseinDEVELOPMENT.mdkeeps it there.- The CHANGELOG. The 2.2.5 section has #473, #475, #481, #483 and #493. It includes the sentence about plaintext predicates that I asked for in my review of #493. #491 and #495 add tests only.
Cargo.toml. No dependency requirement changed. The updates are in the lockfile only.- Signatures. All 3 commits are verified on GitHub.
What I ran
cargo auditon the base, this PR andmain: 29, 19 and 17 advisories.cargo update -p rustls --precise 0.23.45and-p postgres-protocol --precise 0.6.12, thencargo buildandcargo test -p cipherstash-proxy --lib: 282 of 283 passed. The failure,config::tandem::tests::prometheus_config, is the known environment race. I reverted the lockfile after the run.- CI: all 4 checks pass.
|
Thanks @freshtonic. I checked your two commits and they're fine. I pushed one more signed commit, 07ffc15: postgres-protocol goes to 0.6.12 for RUSTSEC-2026-0179/0180, with the CHANGELOG entry updated. It's lockfile only. It builds with Generated by Claude Code |
Bring the security patches that main already carries to release/2.2: - rustls-webpki 0.103.14 - rand 0.9.3 and 0.10.2 - quinn-proto 0.11.15 - hickory-proto and hickory-resolver 0.26.3, via reqwest 0.13.4 - diesel 2.3.12 - postgres-protocol 0.6.12 (including an unbounded SCRAM iteration count from a malicious server), which adds md-5 0.11 and sha2 0.11 beside the existing versions Lockfile only; no code changes were needed.
rustls 0.23.28 has RUSTSEC-2026-0285 (TLS 1.3 handshake messages accepted across encryption levels). main already ships 0.23.45. rustls is Proxy's TLS server for clients and its TLS client to PostgreSQL. The CHANGELOG entry now names rustls and aws-lc-rs/aws-lc-sys, and no longer says that 2.2.5 has every fix that 3.x ships.
The Multitudes endpoint has returned 500 on every release run since 2026-08-17, so the v2.2.5 release run would end red after the images are published. main removed this step in #477.
07ffc15 to
303f809
Compare
Scope the ZeroKMS cipher to CS_DEFAULT_KEYSET_ID whenever a connection has not selected an override. Previously Proxy only checked that the setting existed, then passed no identifier to ScopedCipher and could silently use the client's account default instead. Application-encrypted payloads use the configured keyset explicitly. When the account and configured defaults differ, Proxy derived searchable-encryption metadata with another index key and rejected valid inbound ciphertext during authentication. Preserve connection-level keyset precedence while making the configured fallback effective. Signed-off-by: James Sadler <james@cipherstash.com>
Bind rewrites pair encrypted values with parameters by position. ZeroKms::encrypt padded a short result from encrypt_eql with None, and Bind skips a None value, so the parameter's original plaintext was forwarded to PostgreSQL. ZeroKms::encrypt and Context::encrypt now fail with EncryptionResultCountMismatch when they receive fewer ciphertexts than values sent for encryption.
Proxy keeps a Statement only for statements that touch encrypted columns. A Bind naming a statement Proxy had no record of was treated as plaintext and its values sent as they were, so any path that lost or dropped a statement too early would send plaintext for an encrypted column. Every Parse already records the statement's session, so while mapping is enabled a Bind to a name with no recorded Parse now fails closed with SQLSTATE 26000, PostgreSQL's own code for a missing prepared statement. The refusal goes through PostgreSQL as other refusals do, and the connection stays usable.
The mapper never inferred the DO UPDATE SET assignments of an INSERT ... ON CONFLICT, so a literal or param assigned to an encrypted column on the conflict path was left untyped and sent to PostgreSQL as plaintext. Because the statement still type-checked, the refusal of writes Proxy cannot type check did not catch it. Each assignment value is now unified with the type stored in its target column, as in a plain UPDATE, so it is encrypted. The `excluded` pseudo-table is brought into scope so `excluded.<col>` carries the column's EQL type, and the insert target is named so qualified references resolve. A conflict target on an encrypted column, MySQL INSERT ... SET and ON DUPLICATE KEY UPDATE are rejected. This is the ON CONFLICT part of the mapper fix on main. Its window, aggregate and SELECT ... INTO changes are left out: those gaps act on ciphertext rather than forwarding plaintext.
tokio-postgres 0.7.18 follows the convention that an error's Display describes only that error, with the cause reached through source(), so err.to_string() logs a bare "db error" and drops the server's message. Add ErrorChain, a Display wrapper that walks source(), and use it at the log sites that can carry a database error. Recording the error as a dyn Error field is not enough: the Structured (JSON) format, the default off a terminal, renders only Display. ErrorChain skips a cause the message already ends with, so variants that embed their cause in Display are not printed twice.
tokio-postgres 0.7.18 no longer appends the cause to Error's Display, so assertions on err.to_string() see a bare "db error". Assert on the structured error instead: assert_db_error reads the severity and message off as_db_error(), and assert_client_error reads the kind off Display and the detail off source(). The exact customer-visible message text, including the docs/errors.md links, stays pinned.
…advisories - rustls 0.23.46 (RUSTSEC-2026-0346, 0347, 0348 and 0349) - rustls-webpki 0.103.16 (RUSTSEC-2026-0382) - webpki-root-certs 1.0.11 (RUSTSEC-2026-0383) - tokio-postgres 0.7.18 (RUSTSEC-2026-0178, a panic on a malformed DataRow), which also updates libredox, postgres-types and whoami - h2 0.4.20 (RUSTSEC-2026-0258) - crossbeam-epoch 0.9.21 (RUSTSEC-2026-0204) - tokio 1.51.6 (RUSTSEC-2026-0386) - chacha20 0.10.2, replacing the yanked 0.10.0 tokio-postgres 0.7.18 no longer enables socket2 0.5's "all" feature, which Proxy relied on for TcpKeepalive::with_retries, so Proxy now enables it itself.
Bump the workspace version to 2.2.5, move the unreleased changes into a 2.2.5 CHANGELOG section and add its compare links. Set `latest=false` on the Docker metadata steps so that publishing a 2.2.x release does not move the `cipherstash/proxy:latest` tag off 3.x. Document how 2.2.x maintenance releases are cut from release/2.2: the manual tag steps, `--latest=false`, and `--notes-start-tag` so the generated notes start from the previous 2.2.x tag.
303f809 to
49c7057
Compare
|
All four Test jobs fail on 49c7057. Unit tests pass, but in the integration stage the proxy container never accepts connections on localhost:6432 ("Unable to connect to localhost:6432 after 20 attempts"). 303f809, which has the same tree as 07ffc15, was green, so the cause is in the 7 backport commits on top of it. The most likely one is the dependency update e8af865 (tokio-postgres 0.7.18, rustls 0.23.46, tokio 1.51.6, socket2 Generated by Claude Code |
Requested by Toby
Prepare-release PR for 2.2.5, the next 2.2.x maintenance release, cut from
release/2.2.Changes
2.2.5(Cargo.toml,Cargo.lock).[Unreleased]fixes into a## [2.2.5]CHANGELOG section, with its compare link, so the release workflow'sverify-releasecheck passes for tagv2.2.5.flavor: latest=falseon bothdocker/metadata-actionsteps inrelease.yml. The defaultlatest=autowould tag any non-prerelease semver release ascipherstash/proxy:latest, which must stay on 3.x.### SecurityCHANGELOG entry. tokio-postgres stays on 0.7.13 (0.7.18 conflicts through cipherstash-client); that advisory is left for 2.2.6.release.yml, as ci: remove the Multitudes deployment notification #477 did onmain.release/2.2in DEVELOPMENT.md.Included in 2.2.5
DISCARD ALLandRESET(fix(proxy): reset keyset and mapping settings on DISCARD ALL and RESET (2.2.x, CIP-5021) #475).CIPHERSTASH.*settings in step with PostgreSQL transactions (fix(proxy): keep CIPHERSTASH settings in step with PostgreSQL transactions (2.2 backport, CIP-5073) #481).COPY ... FROM STDINinto plaintext tables, refuse it into encrypted columns (fix(proxy): forward COPY FROM STDIN into plaintext tables, refuse it into encrypted columns (2.2, CIP-5101) #483).The
## [2.2.5]date is set to today; I'll move it to the tag date if tagging happens later.Cutting the release after merge
mise run releaseonly runs onmain, so tag manually from the merged commit onrelease/2.2:Acknowledgment
By submitting this pull request, I confirm that CipherStash can use, modify, copy, and redistribute this contribution, under the terms of CipherStash's choice.
Generated by Claude Code