Skip to content

fix: reject SharedArrayBuffer in WebCrypto and getRandomValues#1019

Merged
boorad merged 2 commits into
mainfrom
fix/reject-sharedarraybuffer-webcrypto
May 4, 2026
Merged

fix: reject SharedArrayBuffer in WebCrypto and getRandomValues#1019
boorad merged 2 commits into
mainfrom
fix/reject-sharedarraybuffer-webcrypto

Conversation

@boorad
Copy link
Copy Markdown
Collaborator

@boorad boorad commented May 4, 2026

Summary

Rejects SharedArrayBuffer and SAB-backed views from WebCrypto (subtle.*) and getRandomValues per WebIDL §BufferSource — concurrent writes from another worker during async crypto can race with the algorithm and corrupt output or leak intermediate state, so even copying the source isn't safe (the copy itself races). Throws TypeError, matching Node's lib/internal/webidl.js BufferSource converter (Node commit bee10872588) and the W3C WebCrypto spec.

Changes

  • New rejectSharedArrayBuffer(buf) helper in utils/conversion.ts that throws TypeError for raw SharedArrayBuffer inputs and views backed by one.
  • Wired into the three buffer-conversion entry points: abvToArrayBuffer (random ops), bufferLikeToArrayBuffer (subtle.* ops), and binaryLikeToArrayBuffer (key material).
  • Explicit early call in getRandomValues so the WebIDL TypeError is thrown before the WebCrypto-specific TypeMismatchError / QuotaExceededError checks — load-bearing for spec error-type ordering, not redundant.
  • Removed the old "copy SAB to AB" fallback in bufferLikeToArrayBuffer, which had a TOCTOU race during the copy itself.
  • Documented that the guard is intentionally stricter than Node: Node's classic crypto APIs (createHash().update, createHmac().update, createCipheriv().update, etc.) accept SAB-backed views, but the same race concern applies on either side of the WebCrypto / classic line, so we apply the safer default everywhere.

Testing

New test suite subtle.sharedarraybuffer-rejection (16 tests) covers raw SAB and SAB-backed views across:

  • getRandomValues
  • crypto.randomFill / randomFillSync
  • subtle.digest (data — view + raw SAB)
  • subtle.encrypt / decrypt (plaintext, iv, ciphertext, AES-GCM additionalData, AES-CTR counter)
  • subtle.sign / verify (data, signature)
  • subtle.importKey (raw key)
  • subtle.deriveBits (HKDF salt)

Suite skips cleanly on hosts that don't expose SharedArrayBuffer (older Hermes builds).

Test plan

  • Tests pass in the example app on iOS
  • Tests pass in the example app on Android
  • No regression in existing WebCrypto / random suites

closes #999

boorad added 2 commits May 3, 2026 21:00
Per WebCrypto / Web IDL §BufferSource, SharedArrayBuffer-backed inputs
must be rejected from all subtle.* methods and getRandomValues:
concurrent writes from another worker during async crypto can race
with the algorithm, corrupting output or leaking intermediate state.
Even copying the source isn't safe — the copy itself races.

Add `rejectSharedArrayBuffer` in conversion.ts and wire it into
abvToArrayBuffer / bufferLikeToArrayBuffer / binaryLikeToArrayBuffer
so every WebCrypto entry point and randomFill* path rejects both raw
SAB and SAB-backed views with TypeError, matching Node's WebIDL
BufferSource converter (commit bee10872588). Also call it explicitly
at the top of getRandomValues so SAB rejection precedes the
TypeMismatchError / QuotaExceededError checks per spec ordering.
Adds two tests verifying SharedArrayBuffer-backed inputs are rejected at
the AES-GCM `additionalData` and AES-CTR `counter` parameters, both of
which flow through `bufferLikeToArrayBuffer` like other BufferSource
fields. Also documents that the SAB guard intentionally applies to
classic crypto APIs too (stricter than Node) since the TOCTOU concern
is identical, and clarifies in `getRandomValues` that the explicit
`rejectSharedArrayBuffer` call is load-bearing for WebIDL error-type
ordering, not redundant. Replaces an `as never` cast in the deriveBits
test with a typed `satisfies HkdfAlgorithm` literal.
@boorad boorad self-assigned this May 4, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

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

Project Deployment Actions Updated (UTC)
react-native-quick-crypto Ready Ready Preview, Comment May 4, 2026 1:15am

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

🤖 End-to-End Test Results - iOS

Status: ✅ Passed
Platform: iOS
Run: 25296355527

📸 Final Test Screenshot

Maestro Test Results - ios

Screenshot automatically captured from End-to-End tests and will expire in 30 days


This comment is automatically updated on each test run.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

🤖 End-to-End Test Results - Android

Status: ✅ Passed
Platform: Android
Run: 25296355542

📸 Final Test Screenshot

Maestro Test Results - android

Screenshot automatically captured from End-to-End tests and will expire in 30 days


This comment is automatically updated on each test run.

@boorad boorad merged commit 39551e4 into main May 4, 2026
9 checks passed
@boorad boorad deleted the fix/reject-sharedarraybuffer-webcrypto branch May 4, 2026 01:31
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.

WebCrypto: reject SharedArrayBuffer in all subtle.* and getRandomValues inputs

1 participant