passkey-kit 0.16.2 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,8 +5,8 @@ A TypeScript SDK for creating and using **smart-wallet accounts on Stellar with
5
5
  - **Client (`PasskeyKit`)** — runs in the browser: create/connect wallets, sign transactions, build signer-management transactions. Holds no secrets.
6
6
  - **Server (`PasskeyServer`)** — runs server-side: submits transactions through a relayer (fee sponsorship), plus convenience signer-discovery helpers over the keyless Mercury indexer. Holds the relayer secret.
7
7
 
8
- > [!IMPORTANT]
9
- > **Security.** Review the contract and SDK yourself before holding meaningful value, and read [Caveats](#caveats).
8
+ > [!CAUTION]
9
+ > **Unaudited software.** This repository's smart-wallet contract, SDKs, and relayer proxy have not received an independent third-party security audit. Defects can cause unauthorized transactions, loss of access, or permanent asset loss. Do not store or control assets you cannot afford to lose. Limit balances and signer permissions. Monitor wallets and maintain recovery and authorized upgrade paths. You use this software and related services at your own risk. The software has no warranty; see [LICENCE](./LICENCE), [Caveats](#caveats), and [SECURITY.md](./SECURITY.md).
10
10
 
11
11
  > [!NOTE]
12
12
  > **Looking for context rules, thresholds, and spending-limit policies?** [smart-account-kit](https://github.com/stellar/smart-account-kit) is a sibling SDK built on the audited [OpenZeppelin stellar-contracts](https://github.com/OpenZeppelin/stellar-contracts) account. It uses a different on-chain authorization model (context rules + an auth digest) than passkey-kit's flat `Signatures` map, so the two are not drop-in compatible — pick the model that fits your app.
@@ -70,8 +70,8 @@ import { PasskeyKit } from "passkey-kit";
70
70
  const kit = new PasskeyKit({
71
71
  rpcUrl: "https://soroban-testnet.stellar.org",
72
72
  networkPassphrase: "Test SDF Network ; September 2015",
73
- // Canonical v1 smart-wallet WASM hash (testnet); see docs/deployments-*.md
74
- walletWasmHash: "fdefad64b96837147e1c333e51f537b696eab925e9f147e63d597c04e3c903f0",
73
+ // Canonical smart-wallet WASM hash; see docs/deployments-*.md
74
+ walletWasmHash: "502ea4e7bdb3ea99880941f1d35ceb67fb598692c0bb40f842ef9c9f17d58b58",
75
75
  });
76
76
  ```
77
77
 
@@ -235,7 +235,7 @@ Each method builds an `AssembledTransaction` (`WalletTx`) that wraps one contrac
235
235
  | `updateEd25519(publicKey, limits, store, expiration?)` | `update_signer` | Update an Ed25519 signer. |
236
236
  | `addPolicy(policy, limits, store, expiration?)` | `add_signer` | Add a policy signer (`policy` = `C…`). Invokes the policy's `install` hook. |
237
237
  | `updatePolicy(policy, limits, store, expiration?)` | `update_signer` | Update a policy signer. |
238
- | `remove(signerKey)` | `remove_signer` | Remove a signer. No policy code runs on this path. |
238
+ | `remove(signerKey)` | `remove_signer` | Remove a signer. A policy entry must pass its own `policy__` check. |
239
239
  | `upgrade(newWasmHash)` | `upgrade` | Replace the wallet's WASM (`Buffer`/`Uint8Array`, 32 bytes). |
240
240
  | `getSigner(signerKey)` | `get_signer` | Read a signer entry from the ledger (temporary before persistent). Returns `SignerVal \| null`. |
241
241
 
@@ -427,6 +427,11 @@ type SignerLimits = Map<string, SignerKey[] | undefined> | undefined;
427
427
  - `Map` present but a contract → `undefined` — may authorize any call to that contract, no co-signers.
428
428
  - `Map` present, contract → `[keys]` — may authorize calls to that contract **only if every listed key also approves** (required co-signers).
429
429
 
430
+ A required policy key must remain installed as a signer and unexpired. Removing
431
+ that policy immediately revokes every signer whose limits require it. A
432
+ `Signature::Policy` always invokes `policy__`, including for the policy's own
433
+ `remove_signer` context.
434
+
430
435
  ```ts
431
436
  // This signer may only call C…token, and only alongside a passkey co-signer.
432
437
  const limits = new Map([["C…token", [SignerKey.Secp256r1(keyId)]]]);
@@ -450,13 +455,16 @@ Signer and signature expiration are **UNIX timestamps in seconds** (inclusive: v
450
455
  ## Caveats
451
456
 
452
457
  > [!WARNING]
453
- > These are inherent to the wallet model. The SDK does not guard against them handle them in your app.
458
+ > These risks are not exhaustive. Tests and reviews do not prove that the software has no defects.
454
459
 
460
+ - **Limit value and authority.** Limit wallet balances, signer permissions, policy allowances, and relayer permissions. Monitor wallet activity. Keep independent recovery, submission, and authorized upgrade paths.
461
+ - **Hosted services can fail or return stale data.** Do not treat relayer or indexer responses as authoritative chain state. Confirm security-sensitive state through Stellar RPC.
455
462
  - **Keep at least one durable admin signer.** The contract rejects any change that would remove or demote its last durable (`Persistent`, non-expiring) admin signer (`LastAdminSigner = 103`) or leave it without any durable signer (`LastSigner = 104`), so a wallet always retains one signer that cannot evict or expire. Signers outside that guard — `Temporary` storage or with an expiration — lapse on their own: add a replacement *before* removing or demoting an existing signer.
456
463
  - **The default deployer is a shared, public keypair — its secret is publicly derivable.** It salts deployment and signs only the CreateContractV2 authorization entry; the relayer supplies the envelope source, sequence, and fees. It never controls the wallet. Its determinism is load-bearing for discovery: overriding `deploySource` changes every derived address and breaks keyId → wallet lookup. Use a separate funded `restoreSource` for `restoreFootprint`; never fund the shared deployer. A third-party `bumpSequence` to `INT64_MAX` no longer blocks the current SDK because it never uses the shared deployer as an envelope source. Full analysis: [`docs/security-deterministic-deployer.md`](docs/security-deterministic-deployer.md).
457
464
  - **Deploy front-running remains an accepted residual.** Anyone who learns a `keyId` before deployment could place arbitrary code at the derived address. A signer getter check alone is not proof of ownership, because arbitrary code can answer it however the client expects. Since `0.16.0` `connectWallet` binds accepted code identity (`acceptedWasmHashes`) before reading any signer state, for any address that did not come from trusted local storage. A derivation-resolved address is still not authenticated by that check alone — see the [security analysis](docs/security-deterministic-deployer.md#accepted-residual-address-squatting).
458
465
  - **WebAuthn requires User Presence (UP), not User Verification (UV).** The contract requires the UP flag but not UV (biometric/PIN), so it stays compatible with non-UV authenticators. Enforce UV at the client/relayer layer if you need it.
459
466
  - **Value-moving policies need a cumulative cap or a co-signer.** A `Signature::Policy` carries no secret, so a per-transfer cap alone is trivially drained by repeated capped transfers. See the [contract interface](#contract-interface) and `sample-policy`.
467
+ - **Existing `binver = 1.0.0` wallets require an authorized upgrade.** Installing the fixed WASM does not change deployed wallet instances. Upgrade each wallet to the canonical `binver = 1.0.1` hash in the current deployment manifest.
460
468
 
461
469
  ## Contract interface
462
470
 
@@ -491,7 +499,7 @@ contractId = sha256(XDR(HashIdPreimage::EnvelopeTypeContractId {
491
499
  - The canonical deployer keypair is `Keypair.fromRawEd25519Seed(sha256("kalepail"))`. It salts the deploy and signs the deploy authorization — it never pays fees and never controls the wallet — but its determinism is **load-bearing**: overriding `deploySource` changes every derived address and breaks keyId → wallet discovery.
492
500
  - The WASM hash is deliberately **not** in the preimage, so an `upgrade` never moves a wallet's address.
493
501
 
494
- This tuple is normative and must never change. See [`docs/deployments-testnet-2026-07-11.md`](./docs/deployments-testnet-2026-07-11.md) for the canonical WASM hashes, the deployer `G…` address, and the full derivation spec (including the deploy-front-running consequence in [Caveats](#caveats)).
502
+ This tuple is normative and must never change. See [`docs/deployments-2026-08-19.md`](./docs/deployments-2026-08-19.md) for the canonical WASM hash, upload transactions, and upgrade guidance.
495
503
 
496
504
  ## Repository layout & development
497
505
 
@@ -512,6 +520,7 @@ pnpm verify:bindings # assert the committed bindings match the canonical WASM
512
520
  ```
513
521
 
514
522
  - **[CHANGELOG.md](./CHANGELOG.md)** — the v1 overhaul, by component.
523
+ - **[SECURITY.md](./SECURITY.md)** — supported versions and private vulnerability reporting.
515
524
  - **[docs/migration-v1.md](./docs/migration-v1.md)** — upgrading from 0.12.x, with Before/After and a gap analysis.
516
525
  - **[docs/releasing.md](./docs/releasing.md)** — the dependency-ordered publish flow.
517
526
 
package/SECURITY.md ADDED
@@ -0,0 +1,27 @@
1
+ # Security Policy
2
+
3
+ ## Security status
4
+
5
+ The smart-wallet contract, SDKs, and repository relayer proxy have not received an independent third-party security audit.
6
+
7
+ Tests and reviews reduce risk. They do not prove that the software has no defects.
8
+
9
+ Do not store or control assets you cannot afford to lose. Limit balances and permissions. Monitor wallets and maintain recovery and authorized upgrade paths.
10
+
11
+ ## Supported versions
12
+
13
+ Only the latest npm releases and the canonical smart-wallet WASM receive security fixes.
14
+
15
+ The current deployment manifest in [`docs/`](./docs/) identifies the canonical WASM. Existing wallet instances do not upgrade automatically.
16
+
17
+ ## Report a vulnerability privately
18
+
19
+ Do not open a public issue, pull request, discussion, or chat message for a suspected vulnerability.
20
+
21
+ Email `tyler@stellar.org` with the subject `passkey-kit security report`. If email is unsuitable, request a private channel without including sensitive details.
22
+
23
+ Include the affected version or commit, impact, reproduction steps, and a minimal proof of concept. Do not include secrets or personal data.
24
+
25
+ Use local tests or isolated test accounts. Do not test against public user wallets or move assets that you do not own.
26
+
27
+ The maintainers will confirm receipt, investigate the report, prepare a fix, and coordinate disclosure with the reporter.
package/dist/version.d.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  * Package version — auto-generated from package.json.
3
3
  * @packageDocumentation
4
4
  */
5
- export declare const VERSION = "0.16.2";
5
+ export declare const VERSION = "0.16.4";
6
6
  export declare const NAME = "passkey-kit";
7
7
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -4,6 +4,6 @@
4
4
  */
5
5
  // This file is auto-generated. Do not edit manually.
6
6
  // Run `pnpm run sync-version` (or `pnpm build`) to update.
7
- export const VERSION = "0.16.2";
7
+ export const VERSION = "0.16.4";
8
8
  export const NAME = "passkey-kit";
9
9
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "passkey-kit",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "description": "A helper library for creating and using smart wallet accounts on the Stellar blockchain.",
5
5
  "author": "Tyler van der Hoeven <tyler@stellar.org>",
6
6
  "license": "MIT",
@@ -26,7 +26,8 @@
26
26
  "files": [
27
27
  "dist",
28
28
  "README.md",
29
- "LICENCE"
29
+ "LICENCE",
30
+ "SECURITY.md"
30
31
  ],
31
32
  "dependencies": {
32
33
  "@openzeppelin/relayer-plugin-channels": "^0.20.0",
@@ -35,7 +36,7 @@
35
36
  "base64url": "^3.0.1",
36
37
  "buffer": "^6.0.3",
37
38
  "sac-sdk": "0.4.4",
38
- "passkey-kit-sdk": "0.8.0"
39
+ "passkey-kit-sdk": "0.8.2"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@types/node": "^24.6.0",
@@ -82,6 +83,6 @@
82
83
  "clean": "rm -rf dist packages/passkey-kit-sdk/dist packages/sac-sdk/dist",
83
84
  "build:demo": "cd demo && pnpm --ignore-workspace install && pnpm run build",
84
85
  "deploy:demo": "npx wrangler pages deploy",
85
- "deploy:demo:prod": "npx wrangler pages deploy --branch production"
86
+ "deploy:demo:prod": "npx wrangler pages deploy --branch main"
86
87
  }
87
88
  }