Skip to content

Release JavaScript SDK v17.6.0 - #1111

Draft
stas-schaller wants to merge 11 commits into
masterfrom
release/sdk/javascript/core/v17.6.0
Draft

Release JavaScript SDK v17.6.0#1111
stas-schaller wants to merge 11 commits into
masterfrom
release/sdk/javascript/core/v17.6.0

Conversation

@stas-schaller

@stas-schaller stas-schaller commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Release branch for JavaScript SDK v17.6.0: NSF folder-decryption parity, throttle hardening, per-item delete error surfacing, and key-rotation retry cap.

Changes

New Features

  • PAM settings dbConnectionMethod (KSM-1073): added dbConnectionMethod to PamSettingsConnection

Bug Fixes

  • getFolders() crash safety (KSM-1079): undecryptable folders are now skipped instead of throwing; the remaining folders are returned normally
  • deleteSecret()/deleteFolder() partial failure (KSM-1084): the SDK now surfaces per-item error messages from the server to the caller
  • Shared folder record decryption (KSM-748): records with innerFolderUid in the flat records[] array now use the folder key instead of the app key; this matches the behavior for records in folders[].records[]
  • Throttle retry jitter (KSM-1035): jitter is now one-sided (0 to +25%); server-supplied retry_after is capped at 176s
  • Key-rotation retry cap (KSM-1128): postQuery's {"error":"key"} branch now retries at most 3 times before throwing a typed KeeperError. The server-suggested key_id is validated for shape (positive integer) and membership in the bundled key table before being persisted; an unsupported id can no longer corrupt the stored configuration. PR fix(javascript): KSM-1128 bound server-key-rotation retries in postQuery #1078 merged 2026-08-18.

Maintenance

  • Humanize pass: ticket refs and AI-pattern names removed from core SDK comments
  • Updated minimatch, @babel/core, and handlebars dev dependencies

Breaking Changes

None.

Related Issues

  • KSM-1073, KSM-1079, KSM-1084, KSM-748, KSM-1035, KSM-1128
  • REL-5278

stas-schaller and others added 9 commits July 24, 2026 13:26
#1079)

* chore(javascript): humanize comments and test names on the release branch

Ticket refs belong in commit messages, not code; test names now describe the behavior
under test instead of the ticket that prompted it. No behavior change.
…flat response array (#1076)

Records created via non-SDK clients inside shared folders arrive in the flat
response.records[] with innerFolderUid set, but recordKey is wrapped with the
folder key, not the app key. The unconditional KEY_APP_KEY unwrap caused these
records to be silently skipped. Mirrors the folderKeyMap pattern already
shipped in the Java SDK (KSM-753).
…ap (#1077)

* fix(javascript): KSM-1035 one-sided throttle jitter and retry_after cap

throttleJitter previously returned [-0.25, 0.25), so a retry could fire before
the computed backoff floor and immediately re-trigger the same throttle window.
Narrowed to [0, 0.25), one-sided like the already-shipped Ruby fix (KSM-883).
Also caps a server-supplied retry_after at MAX_THROTTLE_DELAY_SEC (176s), the
same ceiling the exponential branch already reaches on its last retry.

* fix(javascript): address KSM-1035 review feedback

- Fix stale JSDoc on throttleDelay: jitter range is [0, 0.25) not [-0.25, 0.25)
- Update jitter-bounds unit test to reflect one-sided range (floor is 11s not 8.25s)
- Add 17.6.0 CHANGELOG entry for KSM-1035
All three are dev-only in this package (ts-jest transitive chain), never
shipped:
- minimatch -> 9.0.9 (CVE-2026-27903, CVE-2026-27904 ReDoS)
- @babel/core -> 7.29.7 (CVE-2026-49356, arbitrary file read via
  sourceMappingURL)
- handlebars -> 4.7.9 (CVE-2026-33938, CVE-2026-33941)

Lockfile-only, no package.json range changes. Cherry-picked and scoped
to sdk/javascript/packages/core/package-lock.json from 831b7b48,
efde007d, and b9aef2fa (Sergey Aldoukhov).

KSM-1217
@stas-schaller stas-schaller changed the title feat(javascript): JavaScript SDK v17.6.0 Release JavaScript SDK v17.6.0 Aug 18, 2026
stas-schaller and others added 2 commits August 18, 2026 12:03
…ery (#1078)

* fix(javascript): KSM-1128 bound server-key-rotation retries in postQuery

postQuery's error === 'key' branch (default, no custom server key pinned)
saved the server's suggested key_id and retried with no iteration cap. A
server that keeps rejecting the suggested key would retry forever. Adds a
keyRotationAttempt counter bounded by MAX_KEY_ROTATION_RETRIES (3), mirroring
the existing throttleAttempt/MAX_THROTTLE_RETRIES pattern in the same loop.

* fix(javascript): address KSM-1128 review feedback

- Import KeeperError for use at throw sites
- Validate key_id before persisting: reject non-integer or non-positive values with KeeperError
- Replace plain Error with KeeperError at all key-rotation throw sites
- Tighten rotation-bound test: assert calls === 4 (MAX_KEY_ROTATION_RETRIES + 1), remove loose guard
- Add happy-path test: single key rotation resolves on the retry

* fix(javascript): KSM-1128 complete review feedback

Blocking issue: Validate suggested key_id membership in keeperPublicKeys range.
Unsupported key ids (outside 7-18) now throw typed KeeperError instead of silently
persisting invalid config. Membership check is gated after custom-key check to
preserve IL5 deployment support.

Non-blocking improvements:
- Diagnostic message now names the transmission key id actually attempted, not a
  future suggestion that was never sent.
- Runaway loop guards in all key rotation tests prevent silent jest hang if retry
  bound breaks.
- Better adoption verification: second test uses key_id 8 (not default 7) and
  asserts both transmission key and storage reflect the new id.
- Helper functions (FAKE_ONE_TIME_TOKEN, keyErrorResponse) reduce duplicate
  literals and improve test maintainability.

All 57 tests pass.

* fix(javascript): KSM-1128 add membership check test and changelog

Add regression test for unsupported key_id rejection to prevent silent config
poisoning. Server response with unsupported key_id (e.g. 99) now correctly:
- Makes exactly 1 network request (no retry loop)
- Throws typed KeeperError with clear message
- Does not persist the invalid id to storage

Also add changelog entry documenting the key rotation bounding and validation
improvements in v17.6.0.

All 58 tests pass.

* fix(javascript): KSM-1128 move shape guard below customKey branch

When the server sends {"error":"key"} to a client with a pinned custom
server public key (IL5 config), the IL5 diagnostic now always fires
regardless of whether key_id is present or valid. Previously the shape
guard above the customKey check intercepted malformed key_id values and
produced a generic error instead of the actionable IL5 message.

* fix(javascript): KSM-1128 apply non-blocking cosmetic fixes

- IL5 diagnostic falls back to transmissionKey.publicKeyId when
  storage has no serverPublicKeyId yet, so the message never
  reads "id null"
- Membership error derives the supported range from keeperPublicKeys
  keys at runtime instead of the hardcoded literal "7-18", so the
  message stays accurate when a new key is added to the table

* fix(javascript): KSM-1128 rename rotation tests to behavior-based names

The three tests added for the retry bound and membership check were
prefixed "IL5 dynamic key - ..." but they test generic postQuery
rotation behavior, not IL5-specific code paths. Renamed to describe
what each test asserts.
…1254) (#1135)

* fix(javascript): Node platform hash() ignores tag parameter (KSM-1254)

hash() hardcoded 'KEEPER_SECRETS_MANAGER_CLIENT_ID' instead of hashing
with its tag parameter, unlike the browser implementation and the
Platform contract. No behavior change for the SDK's only caller, which
already passed that same string as the tag.

* test(javascript): pin the client id digest and guard Node/browser hash parity

The two tests already on this branch prove hash() honors its tag, but nothing
holds the result to a value computed outside the SDK, and nothing holds the two
platform implementations to each other. Both gaps are what let the Node
implementation hardcode its tag unnoticed since the initial commit: TypeScript
accepts a lower-arity function for a higher-arity signature, so the compiler
never objected, and every call site inside the SDK passes the one tag the buggy
code hardcoded, so no integration-level test could tell the two apart.

Add a separate file so the stacked KSM-1209 work, which appends to
nodePlatform.test.ts, rebases without a conflict.

- Pin the client id digest for a fixed key against a value cross-checked with
  the Python SDK's hmac.new(client_key_bytes, CLIENT_ID_HASH_TAG, 'sha512'),
  rather than recomputing it with the same call the implementation makes.
- Assert the Node and browser implementations agree on a tag that appears
  nowhere in the SDK, which is the only input that separates an implementation
  honoring its tag from one hardcoding CLIENT_ID_HASH_TAG.

Verified against the pre-fix implementation: the parity test fails, and the
pinned digest still passes, which is the evidence for this branch's claim that
the fix changes no behavior for existing callers.

---------

Co-authored-by: Mateo Gallego <mgallego@keepersecurity.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants