Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Added

- **Application-generated EQL values in statements**: SQL literals and bound parameters may now carry EQL v3 storage payloads or query-only SEM operands produced by an application. Proxy authenticates every stored ciphertext, requires its authenticated descriptor to name the inferred destination column, and independently re-derives every SEM term before forwarding it without double encryption. Query-only operands contain no ciphertext to authenticate, so Proxy instead validates their version, identifier, term shape, column capabilities, and syntactic query role; they are rejected in storage positions. This includes bare SteVec selector hashes matching `^[0-9a-f]{32}$`: in JSON selector query positions a match is treated as already hashed, while a non-match remains plaintext and is encrypted normally. A matching plaintext selector is inherently ambiguous and is intentionally treated as already hashed. Invalid payloads fail closed with one generic, transaction-aborting error so validation details cannot be used as an oracle.

Compatibility note: on encrypted columns, a JSON object with top-level `v` and `i` keys plus at least one of `c`, `h`, or `sv` is reserved as an advertised EQL storage payload. If it is not valid EQL, Proxy rejects it instead of encrypting it as plaintext, and there is no opt-out. Before upgrading, audit plaintext application writes for this key combination; [Invalid encrypted value](docs/errors.md#encrypt-invalid-inbound-ciphertext) includes a `jsonb` scan predicate.

## [3.0.1] - 2026-08-05

### Added
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions docs/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [Internal Error](#mapping-internal-error)

- Encrypt errors:
- [Invalid encrypted value](#encrypt-invalid-inbound-ciphertext)
- [Column could not be encrypted](#encrypt-column-could-not-be-encrypted)
- [Could not decrypt data for keyset](#encrypt-could-not-decrypt-data-for-keyset)
- [KeysetId could not be parsed](#encrypt-keyset-id-could-not-be-parsed)
Expand Down Expand Up @@ -331,6 +332,53 @@ If the error persists, please contact CipherStash [support](https://cipherstash.
# Encrypt errors


## Invalid encrypted value <a id='encrypt-invalid-inbound-ciphertext'></a>

CipherStash Proxy rejected an application-generated EQL storage payload or
query operand because it was malformed, unauthentic, intended for another
column, carried unexpected searchable encrypted metadata (SEM), or appeared in
an invalid statement position. The response deliberately does not identify
which validation failed.

### Error message

```
Invalid encrypted value. For help visit https://github.com/cipherstash/proxy/blob/main/docs/errors.md#encrypt-invalid-inbound-ciphertext
```

### How to fix

Regenerate the payload using the same column configuration, keyset, and
credentials as Proxy. Storage payloads must target the inferred destination
column and carry ciphertext plus exactly its configured SEM terms. Query-only
payloads must be used only in query positions.

### Plaintext compatibility

On an encrypted column, Proxy treats a JSON object as an advertised EQL storage
payload when it has top-level `v` and `i` keys together with at least one of
`c`, `h`, or `sv`. An object matching that key pattern which is not a valid EQL
payload is rejected rather than encrypted as plaintext. There is no opt-out for
this fail-closed check.

Before upgrading, audit JSON values supplied as plaintext to encrypted columns.
For a `jsonb` source column named `value`, this predicate identifies the
ambiguous shape:

```sql
WHERE value ? 'v'
AND value ? 'i'
AND value ?| ARRAY['c', 'h', 'sv']
```

For text sources, first restrict the scan to values that your application knows
are valid JSON, then apply the same predicate after casting them to `jsonb`.
Rename one of these top-level keys or generate the value as an EQL payload
before sending it through Proxy.

<!-- ---------------------------------------------------------------------------------------------------- -->


## Column could not be encrypted <a id='encrypt-column-could-not-be-encrypted'></a>

The column could not be encrypted.
Expand Down
Loading
Loading