Skip to content

fix(crypto): use Uint8Array for WebCrypto BufferSource (unblocks vitest crypto tests)#50

Open
devin-ai-integration[bot] wants to merge 1 commit into
developfrom
devin/1778634490-fix-crypto-iv-buffer
Open

fix(crypto): use Uint8Array for WebCrypto BufferSource (unblocks vitest crypto tests)#50
devin-ai-integration[bot] wants to merge 1 commit into
developfrom
devin/1778634490-fix-crypto-iv-buffer

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented May 13, 2026

Summary

The 3 tests in src/__tests__/lib/crypto.test.ts (encrypt and decrypt roundtrip, different users produce different ciphertexts, wrong key fails to decrypt) have been failing on main and develop with:

TypeError: Failed to normalize algorithm: 'iv' of 'AesGcmParams' (passed algorithm)
  is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.
 ❯ encrypt src/lib/crypto.ts:53:41

Root cause: src/lib/crypto.ts cast Uint8Array.buffer to ArrayBuffer before handing it to crypto.subtle.encrypt/decrypt/importKey/deriveKey. Under jsdom's stricter WebCrypto realm, the cross-realm ArrayBuffer identity check rejects this as "not an instance of ArrayBuffer". The runtime accepts BufferSource = ArrayBuffer | ArrayBufferView, so passing the Uint8Array directly works in Node, jsdom, browsers, and Edge.

Changes in src/lib/crypto.ts:

  • Helpers renamed textToBuffer/bufferToHex/hexToBuffertextToBytes/bytesToHex/hexToBytes and return Uint8Array<ArrayBuffer> (not ArrayBuffer).
  • Constrained to Uint8Array<ArrayBuffer> (vs the default Uint8Array<ArrayBufferLike>) so TS 5.7+'s BufferSource overload doesn't reject SharedArrayBuffer-backed views.
  • All 4 crypto.subtle.* call sites now pass the Uint8Array directly — no more .buffer as ArrayBuffer casts.

Public API (deriveKey, encrypt, decrypt) signatures and behavior unchanged — encrypt still returns { ciphertext: hexString, iv: hexString } and decrypt accepts the same inputs. Existing ciphertexts in Convex remain decryptable (encoding/decoding path is identical; only the WebCrypto argument types changed).

Verified locally on this branch:

  • bun run test175/175 pass (was 171/174 on develop)
  • npx tsc --noEmit → clean
  • bun run build → clean

Review & Testing Checklist for Human

  • Decrypt an existing API key row that was encrypted by the old code path against the unchanged deriveKey output. (Hex strings are realm-agnostic, so this should be a no-op, but worth confirming against Convex prod data before merging.)
  • Re-run bun run test in CI to confirm the crypto suite is green.
  • Spot-check src/hooks/use-key-store.ts (the only consumer) still behaves correctly in the browser — save a key, reload, retrieve it.

Notes

  • Scope is intentionally narrow: only src/lib/crypto.ts is touched. The repo also has 46 unrelated ESLint errors (mostly react-hooks/set-state-in-effect and @convex-dev/explicit-table-ids) that I left alone — happy to do a follow-up PR if you want.
  • No CI workflow runs tests/lint on PRs in this repo today (only Vercel previews), so the failing crypto tests weren't blocking merges — but bun run test locally is now green again.

Link to Devin session: https://app.devin.ai/sessions/a990fb55f97e422ebe20a0d96226d3ba
Requested by: @Jing-yilin


Open in Devin Review

The previous code cast Uint8Array.buffer to ArrayBuffer when calling
crypto.subtle.encrypt/decrypt/importKey/deriveKey. Under stricter
WebCrypto realms (e.g. jsdom in vitest), the cross-realm ArrayBuffer
identity check rejects this as 'not an instance of ArrayBuffer'. Pass
Uint8Array directly (BufferSource accepts ArrayBufferView) and constrain
helpers to Uint8Array<ArrayBuffer> to satisfy lib.dom's BufferSource
overload (TypeScript 5.7+ Uint8Array is generic over ArrayBufferLike,
which permits SharedArrayBuffer).

Fixes the 3 failing tests in src/__tests__/lib/crypto.test.ts:
  - encrypt and decrypt roundtrip
  - different users produce different ciphertexts
  - wrong key fails to decrypt

Public API of deriveKey/encrypt/decrypt is unchanged.
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tryskills.sh Ready Ready Preview, Comment May 13, 2026 1:41am

Request Review

Copy link
Copy Markdown
Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

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.

1 participant