Skip to content
Merged
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
8 changes: 5 additions & 3 deletions .changeset/lucky-cows-repeat.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

Document in the bundled `stash-auth` skill that `CS_CLIENT_KEY` must be
hex-encoded. Hex is what `stash env` emits and what the skill's variable table
already stated, but older client versions also accepted the base64 spelling
stored in `~/.cipherstash/secretkey.json`, so a key copied out of that file
used to work. It is now rejected at client construction, with a message that
already stated, but the decoder underneath used to fall back to standard padded
base64 — the encoding the Rust `stash-profile` crate uses for
`~/.cipherstash/secretkey.json` on disk — so a key copied out of that file
happened to work despite never being a supported input. That fallback is gone
and such a key is now rejected at client construction, with a message that
deliberately withholds detail — so the skill names the symptom and the fix.

The recovery advice is split by entry point: falling back to the profile store
Expand Down
34 changes: 14 additions & 20 deletions .changeset/olive-pugs-invite.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
---
'@cipherstash/stack': major
'@cipherstash/stack': patch
---

Adopt protect-ffi 0.31.0.

`major`, not `minor`, because of the first item below: a credential encoding
that worked on 1.x stops working at client construction, and `@cipherstash/stack`
pins `@cipherstash/protect-ffi` exactly — so upgrading stack forces the new FFI
and there is no version of this a caller opts into separately. That hex was
always the documented encoding describes intent, not the behaviour anyone was
running against. The fixed group takes `stash`, `wizard` and the three adapters
to 2.0.0 with it; that is a release-management cost, not an argument about what
the version number means.

**`clientKey` must now be hex-encoded.** This is the change to check before
upgrading. The client key used to be decoded by a function that accepted both
hex and standard padded base64 — the encoding `~/.cipherstash/secretkey.json`
stores on disk — so a base64 value in `config.clientKey` or `CS_CLIENT_KEY`
worked even though the documented encoding is hex. It is now rejected at client
construction with `invalid clientKey: expected a hex-encoded key`.
**`clientKey` is hex, and a decoder tolerance that accepted other spellings is
gone.** Hex has always been the documented and only supported encoding for
`config.clientKey` / `CS_CLIENT_KEY` — it is what `stash env` emits and what
the docs and skills have always shown. The decoder underneath happened to fall
back to standard padded base64, which is the encoding the Rust
`stash-profile` crate uses for `~/.cipherstash/secretkey.json` on disk; that
fallback was never part of this package's contract, and nothing in the
JavaScript stack ever produced or accepted a base64 key. It is now rejected at
client construction with `invalid clientKey: expected a hex-encoded key`.
Comment on lines +7 to +15

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the historical acceptance claim.

Line 14 says that the JavaScript stack never accepted a base64 key. The preceding text says that the decoder fallback accepted standard padded base64, and .changeset/lucky-cows-repeat.md says that copied profile keys happened to work. State that base64 was never intentionally supported or produced, but was accepted incidentally.

Proposed wording
-and nothing in the JavaScript stack ever produced or accepted a base64 key.
+and the JavaScript stack never intentionally produced or documented base64; the decoder nevertheless accepted it incidentally.

The PR objective states that base64 worked incidentally through decoder fallback.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**`clientKey` is hex, and a decoder tolerance that accepted other spellings is
gone.** Hex has always been the documented and only supported encoding for
`config.clientKey` / `CS_CLIENT_KEY` — it is what `stash env` emits and what
the docs and skills have always shown. The decoder underneath happened to fall
back to standard padded base64, which is the encoding the Rust
`stash-profile` crate uses for `~/.cipherstash/secretkey.json` on disk; that
fallback was never part of this package's contract, and nothing in the
JavaScript stack ever produced or accepted a base64 key. It is now rejected at
client construction with `invalid clientKey: expected a hex-encoded key`.
**`clientKey` is hex, and a decoder tolerance that accepted other spellings is
gone.** Hex has always been the documented and only supported encoding for
`config.clientKey` / `CS_CLIENT_KEY` — it is what `stash env` emits and what
the docs and skills have always shown. The decoder underneath happened to fall
back to standard padded base64, which is the encoding the Rust
`stash-profile` crate uses for `~/.cipherstash/secretkey.json` on disk; that
fallback was never part of this package's contract, and the JavaScript stack
never intentionally produced or documented base64; the decoder nevertheless
accepted it incidentally. It is now rejected at client construction with
`invalid clientKey: expected a hex-encoded key`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/olive-pugs-invite.md around lines 7 - 15, Update the changeset
text around the clientKey encoding history to clarify that base64 was never
intentionally supported or produced by the JavaScript stack, but was accepted
incidentally through the decoder’s fallback; preserve the distinction between
documented hex support and accidental compatibility with copied profile keys.


The message deliberately says nothing more, because the underlying decode error
names the offending character and its offset and would put part of a live key
into your logs. So if every operation starts failing at construction after this
upgrade, check the encoding of your key first. Re-encode it as hex, or drop the
explicit key and let the client read it from the profile store.
into your logs. So if construction starts failing after this upgrade, the key
you supplied is not hex — re-encode it, or drop the explicit key and let the
native client read it from the profile store.

Reading the key from `~/.cipherstash/secretkey.json` is unaffected — that path
still uses base64, and only an explicitly supplied key is now hex-only.
still uses base64, and only an explicitly supplied key is hex-only.

**DynamoDB errors no longer report foreign error codes as encryption codes.**
`handleError` accepted any string-valued `code` on a caught error and passed it
Expand Down
11 changes: 6 additions & 5 deletions skills/stash-auth/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,12 @@ access key is minted with the member role — the CLI never mints admin keys —
and is shown exactly once. Give each environment its own minted set; see
`stash-deployment` for where each environment's credentials live.

> **`CS_CLIENT_KEY` must be hex.** Hex is what `stash env` emits and what this
> table has always documented, but older versions also accepted the base64
> spelling that `~/.cipherstash/secretkey.json` stores on disk — so a key
> copied out of that file worked. It no longer does: the client now rejects it
> at construction with `invalid clientKey: expected a hex-encoded key`, and
> **`CS_CLIENT_KEY` must be hex.** Hex is what `stash env` emits and the only
> encoding this table has ever documented. The decoder underneath used to fall
> back to standard padded base64 — the spelling `~/.cipherstash/secretkey.json`
> stores on disk — so a key copied out of that file happened to work despite
> never being a supported input. It no longer does: the client rejects it at
> construction with `invalid clientKey: expected a hex-encoded key`, and
> the message says nothing further on purpose (the underlying decode error
> names a character of the key and its offset).
>
Expand Down
Loading