[PR #5791] [MERGED] feat(js-sandbox): add extensive Web Crypto API support #5351

Closed
opened 2026-03-17 02:48:31 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/hoppscotch/hoppscotch/pull/5791
Author: @jamesgeorge007
Created: 1/20/2026
Status: Merged
Merged: 1/22/2026
Merged by: @jamesgeorge007

Base: nextHead: feat/js-sandbox-web-crypto-api-support


📝 Commits (1)

  • 8c0dc5a feat(js-sandbox): add extensive Web Crypto API support

📊 Changes

13 files changed (+3223 additions, -199 deletions)

View changed files

📝 packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/scripting-revamp-coll.json (+195 -137)
packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/encrypt-decrypt.spec.ts (+261 -0)
packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/key-operations.spec.ts (+829 -0)
packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/random-values.spec.ts (+243 -0)
packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/sign-verify.spec.ts (+207 -0)
packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/subtle-digest.spec.ts (+207 -0)
📝 packages/hoppscotch-js-sandbox/src/__tests__/pm-namespace/serialization-edge-cases.spec.ts (+0 -1)
📝 packages/hoppscotch-js-sandbox/src/__tests__/pw-namespace/expect/toBeLevelxxx.spec.ts (+0 -3)
packages/hoppscotch-js-sandbox/src/cage-modules/crypto.ts (+1031 -0)
📝 packages/hoppscotch-js-sandbox/src/cage-modules/default.ts (+2 -2)
📝 packages/hoppscotch-js-sandbox/src/cage-modules/fetch.ts (+5 -56)
📝 packages/hoppscotch-js-sandbox/src/cage-modules/index.ts (+2 -0)
packages/hoppscotch-js-sandbox/src/cage-modules/utils/vm-marshal.ts (+241 -0)

📄 Description

Relates to #2015, #5523, #3353, https://github.com/AndrewBastin/faraday-cage/issues/1.

Closes FE-1104.

This PR brings comprehensive Web Crypto API support to Hoppscotch's experimental scripting sandbox, enabling users to perform real cryptographic operations in their pre-request and test scripts.

A custom in-house implementation of the cage module is maintained to enable faster iteration and project-specific behaviour. The relevant upstream issue is linked for visibility, following the same approach used for the custom fetch cage module.

What's changed

New files:

  • cage-modules/crypto.ts — Custom crypto module implementing the full crypto.subtle API (~1,100 lines). Replaces faraday-cage's built-in crypto, which lacked proper crypto.subtle support across the VM boundary.
  • cage-modules/utils/vm-marshal.ts — Shared utilities for marshalling values between QuickJS VM and host: vmArrayToUint8Array(), uint8ArrayToVmArray(), CryptoKeyRegistry for storing CryptoKey objects, and marshalValue() for generic object serialisation.

Modified files:

  • cage-modules/default.ts — Swapped faraday-cage's crypto for customCryptoModule in the default module set
  • cage-modules/fetch.ts — Refactored to use shared vm-marshal.ts utilities instead of duplicating marshalling logic
  • cage-modules/index.ts — Export the new crypto module and its config type

Test files:

  • Added 5 unit test suites for crypto operations (encrypt/decrypt, sign/verify, key operations, random values, digest).
  • Updated CLI e2e collection with 14 crypto-specific assertions.
  • Fixed circular reference test handling in serialization-edge-cases.spec.ts.
  • Simplified skip annotation in toBeLevelxxx.spec.ts.

Crypto operations now available

  • Hashing: SHA-1, SHA-256, SHA-384, SHA-512
  • Encryption: AES-GCM, AES-CBC, AES-CTR, RSA-OAEP
  • Signatures: HMAC, ECDSA, RSA-PSS, RSA-PKCS1-v1_5
  • Key management: generate, import, export (JWK/raw/PKCS8/SPKI), derive (PBKDF2/HKDF), wrap/unwrap (AES-KW)
  • Random: crypto.getRandomValues(), crypto.randomUUID()

Note to reviewers

Try out the following snippet:

// SHA-256 hashing
const data = new TextEncoder().encode("Hello")
// hash is a plain array of bytes
const hash = await crypto.subtle.digest('SHA-256', data)

// HMAC-SHA256 signature
const key = await crypto.subtle.generateKey(
  { name: 'HMAC', hash: 'SHA-256' },
  false,
  ['sign']
)
const signature = await crypto.subtle.sign('HMAC', key, data)

The main challenge was safely transferring cryptographic values across the QuickJS VM boundary. Since QuickJS doesn't natively support Uint8Array or CryptoKey objects, custom marshalling is used to convert between VM arrays and host types. CryptoKey objects are stored in a host-side registry (with 5-minute TTL) and referenced by ID from the VM.

All operations delegate to the host's native WebCrypto; no cryptographic primitives are implemented here. Async operations are tracked to prevent "use after free" errors when the VM is disposed of while crypto work is pending.

Tests perform real cryptographic round-trips (encrypt→decrypt, sign→verify) rather than just checking function existence.

No breaking changes to the public API.


Summary by cubic

Adds full Web Crypto API support to the Hoppscotch JavaScript sandbox, enabling real hashing, encryption, signing, key management, and random utilities in pre-request and test scripts. Implements a custom crypto module that safely bridges the QuickJS VM to the host WebCrypto.

  • New Features

    • Supports crypto.subtle: digest, encrypt/decrypt (AES, RSA), sign/verify (HMAC, ECDSA, RSA), key generate/import/export/derive/wrap, plus getRandomValues and randomUUID.
    • Delegates all operations to native WebCrypto; no custom crypto primitives.
    • Added unit tests and CLI e2e assertions covering round-trip encrypt/decrypt and sign/verify.
  • Refactors

    • Replaced faraday-cage crypto with customCryptoModule in default modules; exported the module and its config.
    • Introduced shared VM marshalling utilities and a host-side CryptoKey registry (TTL) to pass data/keys across the VM boundary.
    • Updated fetch module to use shared marshalling and simplified serialization types.
    • Minor test cleanups (circular reference handling, reduced skip annotations).

Written for commit 8c0dc5a12e. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/hoppscotch/hoppscotch/pull/5791 **Author:** [@jamesgeorge007](https://github.com/jamesgeorge007) **Created:** 1/20/2026 **Status:** ✅ Merged **Merged:** 1/22/2026 **Merged by:** [@jamesgeorge007](https://github.com/jamesgeorge007) **Base:** `next` ← **Head:** `feat/js-sandbox-web-crypto-api-support` --- ### 📝 Commits (1) - [`8c0dc5a`](https://github.com/hoppscotch/hoppscotch/commit/8c0dc5a12e2b2f84109b694392491e57b4aeac6f) feat(js-sandbox): add extensive Web Crypto API support ### 📊 Changes **13 files changed** (+3223 additions, -199 deletions) <details> <summary>View changed files</summary> 📝 `packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/scripting-revamp-coll.json` (+195 -137) ➕ `packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/encrypt-decrypt.spec.ts` (+261 -0) ➕ `packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/key-operations.spec.ts` (+829 -0) ➕ `packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/random-values.spec.ts` (+243 -0) ➕ `packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/sign-verify.spec.ts` (+207 -0) ➕ `packages/hoppscotch-js-sandbox/src/__tests__/cage-modules/crypto/subtle-digest.spec.ts` (+207 -0) 📝 `packages/hoppscotch-js-sandbox/src/__tests__/pm-namespace/serialization-edge-cases.spec.ts` (+0 -1) 📝 `packages/hoppscotch-js-sandbox/src/__tests__/pw-namespace/expect/toBeLevelxxx.spec.ts` (+0 -3) ➕ `packages/hoppscotch-js-sandbox/src/cage-modules/crypto.ts` (+1031 -0) 📝 `packages/hoppscotch-js-sandbox/src/cage-modules/default.ts` (+2 -2) 📝 `packages/hoppscotch-js-sandbox/src/cage-modules/fetch.ts` (+5 -56) 📝 `packages/hoppscotch-js-sandbox/src/cage-modules/index.ts` (+2 -0) ➕ `packages/hoppscotch-js-sandbox/src/cage-modules/utils/vm-marshal.ts` (+241 -0) </details> ### 📄 Description Relates to #2015, #5523, #3353, https://github.com/AndrewBastin/faraday-cage/issues/1. Closes FE-1104. This PR brings comprehensive Web Crypto API support to Hoppscotch's experimental scripting sandbox, enabling users to perform real cryptographic operations in their pre-request and test scripts. A custom in-house implementation of the cage module is maintained to enable faster iteration and project-specific behaviour. The relevant upstream issue is linked for visibility, following the same approach used for the custom fetch cage module. ### What's changed **New files:** - `cage-modules/crypto.ts` — Custom crypto module implementing the full `crypto.subtle` API (~1,100 lines). Replaces faraday-cage's built-in crypto, which lacked proper `crypto.subtle` support across the VM boundary. - `cage-modules/utils/vm-marshal.ts` — Shared utilities for marshalling values between QuickJS VM and host: `vmArrayToUint8Array()`, `uint8ArrayToVmArray()`, `CryptoKeyRegistry` for storing CryptoKey objects, and `marshalValue()` for generic object serialisation. **Modified files:** - `cage-modules/default.ts` — Swapped faraday-cage's `crypto` for `customCryptoModule` in the default module set - `cage-modules/fetch.ts` — Refactored to use shared `vm-marshal.ts` utilities instead of duplicating marshalling logic - `cage-modules/index.ts` — Export the new crypto module and its config type **Test files:** - Added 5 unit test suites for crypto operations (encrypt/decrypt, sign/verify, key operations, random values, digest). - Updated CLI e2e collection with 14 crypto-specific assertions. - Fixed circular reference test handling in `serialization-edge-cases.spec.ts`. - Simplified skip annotation in `toBeLevelxxx.spec.ts`. ### Crypto operations now available - Hashing: SHA-1, SHA-256, SHA-384, SHA-512 - Encryption: AES-GCM, AES-CBC, AES-CTR, RSA-OAEP - Signatures: HMAC, ECDSA, RSA-PSS, RSA-PKCS1-v1_5 - Key management: generate, import, export (JWK/raw/PKCS8/SPKI), derive (PBKDF2/HKDF), wrap/unwrap (AES-KW) - Random: `crypto.getRandomValues()`, `crypto.randomUUID()` ### Note to reviewers Try out the following snippet: ```js // SHA-256 hashing const data = new TextEncoder().encode("Hello") // hash is a plain array of bytes const hash = await crypto.subtle.digest('SHA-256', data) // HMAC-SHA256 signature const key = await crypto.subtle.generateKey( { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'] ) const signature = await crypto.subtle.sign('HMAC', key, data) ``` The main challenge was safely transferring cryptographic values across the QuickJS VM boundary. Since QuickJS doesn't natively support `Uint8Array` or `CryptoKey` objects, custom marshalling is used to convert between VM arrays and host types. CryptoKey objects are stored in a host-side registry (with 5-minute TTL) and referenced by ID from the VM. All operations delegate to the host's native `WebCrypto`; no cryptographic primitives are implemented here. Async operations are tracked to prevent "use after free" errors when the VM is disposed of while crypto work is pending. Tests perform real cryptographic round-trips (encrypt→decrypt, sign→verify) rather than just checking function existence. No breaking changes to the public API. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds full Web Crypto API support to the Hoppscotch JavaScript sandbox, enabling real hashing, encryption, signing, key management, and random utilities in pre-request and test scripts. Implements a custom crypto module that safely bridges the QuickJS VM to the host WebCrypto. - **New Features** - Supports crypto.subtle: digest, encrypt/decrypt (AES, RSA), sign/verify (HMAC, ECDSA, RSA), key generate/import/export/derive/wrap, plus getRandomValues and randomUUID. - Delegates all operations to native WebCrypto; no custom crypto primitives. - Added unit tests and CLI e2e assertions covering round-trip encrypt/decrypt and sign/verify. - **Refactors** - Replaced faraday-cage crypto with customCryptoModule in default modules; exported the module and its config. - Introduced shared VM marshalling utilities and a host-side CryptoKey registry (TTL) to pass data/keys across the VM boundary. - Updated fetch module to use shared marshalling and simplified serialization types. - Minor test cleanups (circular reference handling, reduced skip annotations). <sup>Written for commit 8c0dc5a12e2b2f84109b694392491e57b4aeac6f. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-17 02:48:31 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hoppscotch#5351
No description provided.