Para’s SDK as Attack Surface

This is a follow-up to The Custody Illusion, which argues that Para’s pregenerated wallet mode is custodial by design despite being marketed as non-custodial. That essay made the architectural case. The concerns here are different: they are implementation-level findings that follow from how Para’s SDK is built, independent of which deployment mode you choose.

The architectural concerns in The Custody Illusion follow from the deployment model regardless of implementation quality. But the implementation introduces its own risks worth naming.

Runtime code loading without integrity verification

On its first signing operation in a given process, Para’s server SDK fetches the MPC worker code from Para’s servers at runtime and passes the response body directly to new Worker(code, { eval: true }), which executes the fetched JavaScript inside a Node worker thread. There is no Subresource Integrity check, no signature verification, no bundled fallback. In production, this fetches JavaScript from Para’s static asset hosting over TLS.

The consequence: integrating Para’s server SDK expands the trust assumption from “Para is honest about MPC signing” to “Para’s static asset hosting will never be compromised and will never serve malicious worker JavaScript.” A compromise of Para’s CDN, a rogue employee with write access to the asset bucket, a supply-chain attack on Para’s worker build pipeline, or a sufficiently privileged TLS man-in-the-middle would all grant arbitrary code execution inside the integrator’s process. The compromised worker sits on the receiving end of every postMessage the SDK sends — which is exactly where the user share is delivered for signing. Every signing operation during the compromise window hands the malicious worker the share material it was sent to operate on.

This is low-probability but high blast radius, and it is the kind of finding that surfaces in any serious security audit. The risk is inherent to the SDK’s architecture, not a bug to be patched.

Shared worker process

Para’s SDK uses a module-level singleton worker thread for MPC operations. All wallet instances in the same process share a single worker. The worker’s error and exit handlers reject every in-flight signing operation across all tenants at once. A worker crash from memory pressure, a WebAssembly panic, or a malformed message from any single tenant takes down all concurrent signing operations in that process. This is an availability concern rather than a security one, but it is worth naming for any platform running multi-tenant workloads.

Why this matters separately

The architectural critique in The Custody Illusion is that the deployment configuration voids the security property the marketing depends on. These implementation findings are different in kind — they would matter even if the deployment were architecturally sound.

The runtime code loading pattern is not specific to the server SDK. Para’s core SDK uses the same approach to fetch a worker bundle from getPortalBaseURL/static/js/... for client-side flows. Both modes fetch a worker bundle from Para’s servers at runtime, with no integrity check. The architectural problem is mode-specific. The implementation problem is not.

In a security audit, these would surface as distinct findings: one about the custody model, one about supply chain assumptions, one about availability under multi-tenancy. They share a vendor, not a root cause.