# Side Impactor signs an IPA and installs it over WebUSB, entirely in the browser

> Side Impactor is a MIT licensed pure frontend web application that pairs an iOS device over WebUSB, re-signs an IPA with your own Apple Developer account and installs it, with a Cloudflare Workers relay and a stack of WebAssembly ports doing the protocol work. It suits a developer testing their own builds, and it is a browser tool that needs a Chromium browser and a paid developer account.

**lbr77/SideImpactor** — pure frontend ipa signing page.

- Repository: https://github.com/lbr77/SideImpactor
- Website: https://sideload.nvme0n1p.dev
- Stars: 578 · Forks: 74
- Language: JavaScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/lbr77-sideimpactor

## The whole flow runs in a browser tab over WebUSB

Side Impactor is described as a pure frontend IPA signing page, and the summary line is browser-based IPA signing and installation: pair an iOS device over WebUSB, sign with your Apple Developer account, and install, all from a single web page.

The order of operations is the interesting part. The device is paired over WebUSB rather than over a network service, the signing happens with the developer's own credentials, and the install follows. Nothing about that requires a Mac or a Mac-side helper, which is what distinguishes this from the desktop toolchains it credits.

The project structure table explains how the work is divided.

```
| Path | Purpose |
|---|---|
| `frontend/` | React + Tailwind SPA (Vite) |
| `backend/` | Cloudflare Workers relay |
| `dependencies/webmuxd/` | WebUSB usbmux/lockdown protocol library |
| `wasm/openssl/` | OpenSSL WASM (TLS + pair record generation) |
| `wasm/libcurl-wasm/` | libcurl WASM (Apple API HTTP via WISP proxy) |
| `wasm/zsign-wasm/` | zsign WASM (IPA re-signing) |
| `scripts/` | WASM native build scripts (Rust + Emscripten) |
```

Five separate pieces do the heavy lifting. webmuxd speaks the usbmux and lockdown protocols over WebUSB, which is the transport layer Apple's tooling normally uses. OpenSSL compiled to WebAssembly handles TLS and generates the pair record, which is the file that links a device to a computer. libcurl in WebAssembly makes the HTTP calls to Apple's APIs, routed through a WISP proxy. And zsign in WebAssembly does the IPA re-signing itself.

That is a substantial amount of native code compiled for the browser, and the project says so plainly in the table.

## The relay exists because the browser cannot reach Apple directly

The backend is a Cloudflare Workers relay, and understanding why it is there explains the architecture.

The libcurl WASM entry in the structure table says it handles Apple API HTTP via WISP proxy. A WISP proxy is a mechanism for routing a web request through a third party, and it is needed here because the browser page cannot simply make the cross-origin calls that Apple's developer endpoints require, and because the TLS handshake with Apple's servers needs a real crypto stack that the browser will not let a page do on its own.

So the relay is the piece that terminates and forwards the Apple API traffic, and the OpenSSL WASM build exists to give the page genuine TLS for the pair record generation, where a browser's own crypto API would not fit the protocol.

The backend is a separate workspace package with its own build and check script, and it is deployed on its own.

```bash
cd backend
bun run deploy
```

For local work, the dev scripts start the worker and the frontend together, with the worker on port 8787 and the frontend on the Vite dev server, and the README's quick start is two commands.

```bash
bun install --ignore-scripts
bun run dev
```

After that you open http://localhost:5173. The `--ignore-scripts` flag matters, because the setup script runs a git submodule update and compiles the WebAssembly bundles, and the README separates that into its own step.

## Prebuilt WebAssembly bundles, or a full Rust and Emscripten rebuild

The build section offers three levels, and the distinction is the difference between a five minute setup and a compiler toolchain.

```bash
# WASM dist bundles (copies pre-built src→dist, no compiler needed)
bun run build:wasm:dist

# Frontend production build (runs wasm:dist automatically)
bun run build:frontend

# Full WASM recompile from source (requires Rust, Emscripten, precompiled OpenSSL)
bun run build:wasm
```

The dist script is the one that matters for most people. It does not compile anything: it copies the prebuilt sources into the dist directories, symlinking the OpenSSL package and copying the zsign npm output into place. No Rust, no Emscripten, no C toolchain.

The full rebuild is a different proposition. It requires Rust, Emscripten and a precompiled OpenSSL, and it runs three separate shell scripts, one per WebAssembly component, from the scripts/ directory.

The Docker path follows the same logic. The Dockerfile is a two-stage build, with the build stage on oven/bun:1.3-alpine and the serve stage on nginx:1.29-alpine, and the build stage runs bun run build:wasm:dist before the frontend build. So the image ships the prebuilt WebAssembly, not a fresh compile.

```bash
bun run build:wasm:dist   # ensure WASM dists exist
docker build -t sideload-web .
docker run -p 3000:3000 sideload-web
```

The nginx stage serves the built frontend with the nginx.conf at the repository root, and the container exposes port 3000.

## The workspace layout and the pinned toolchain

The root package.json shows the whole project as one Bun workspace with six members.

```json
  "name": "sideload-workspace",
  "private": true,
  "packageManager": "bun@1.3.11",
  "workspaces": [
    "frontend",
    "backend",
    "dependencies/webmuxd",
    "wasm/openssl",
    "wasm/libcurl-wasm",
    "wasm/zsign-wasm"
  ],
```

The package manager is pinned to bun 1.3.11, and the repository carries a bun.lock, so the toolchain is deliberately narrow. There is a .prettierrc for formatting, a .dockerignore for the image build, an nginx.conf for the served frontend, an AGENTS.md for agent-driven maintenance, and a sms-2fa.patch file, which is a patch applied to some dependency and hints at the two factor step in the Apple sign-in flow.

There is also a .gitmodules, so at least one dependency is a git submodule rather than a package, and the setup script runs git submodule update --init before installing.

The scripts section of the package.json is worth reading for what it says about the project's structure. The build script only builds the webmuxd dependency. The test script runs the webmuxd unit tests, and test:frontend runs the frontend suite, which the README describes as a vitest suite of 141 tests.

So there are two test suites, one for the protocol library and one for the interface, and the lint script also targets the webmuxd dependency.

## The credits list is a map of what this borrows

The credits section lists the projects Side Impactor references, and the list is a good description of the design.

libimobiledevice is the long standing open source implementation of Apple's device communication protocols on Linux, and webmuxd is the WebUSB port of the usbmux and lockdown protocol that this project depends on directly. zsign is the IPA re-signing tool, and openssl-wasm is the WebAssembly build of OpenSSL, both from nicehash.

Then there are two projects that are closer to the product. AltSign is a desktop application for sideloading, and AltStore is the well known alternative app store that keeps its apps updated through a companion server. Both are credited, which tells you the workflow being reproduced is the one those tools popularised.

Two of the credits are the author's own projects. anisette-js is a JavaScript implementation of the anisette data used to talk to Apple's servers, and unicorn is the CPU emulator that has a branch, tci-emscripten, for building under Emscripten. The unicorn branch is what makes the local library work in the browser at all.

The Apache 2 licence is stated for the referenced projects, and the project's own licence is MIT, with the LICENSE file at the root of the repository.

## Where this approach stops working

There is a set of practical limits that the documentation does not resolve, and they are worth naming.

The first is the browser. WebUSB is not implemented in Safari, and in practice a Chromium based browser is the requirement, because the project drives the device protocol directly from the page. That is a hard constraint on a tool whose whole premise is that it runs anywhere a page loads.

The second is the relay. Apple API traffic goes through a WISP proxy hosted by the project, and the page is a frontend for a service the author runs. A developer signing with their own Apple Developer account is sending real credentials through infrastructure they do not control, and the documentation here does not describe the relay's retention, logging or authentication model. The hosted instance is at sideload.nvme0n1p.dev, and the same page is what you use unless you deploy the backend yourself with bun run deploy, which is the option to prefer if the credentials matter.

The third is the WebAssembly supply chain. The prebuilt bundles are copied rather than compiled, so the code that signs your application and handles TLS arrives as a binary artefact. Recompiling from source needs Rust, Emscripten and a precompiled OpenSSL, and the project documents that path in the build scripts. Whether you take the prebuilt path or the rebuild path is a decision about how much you verify, and the README makes the difference clear without telling you which to choose.

Finally, the whole approach is per device. Pairing is over USB, so the browser tab, the cable and the phone all have to be in the same room, and none of this works for a device on the other side of the house.

## Conclusion

Side Impactor fits a developer who needs to put a build of their own app onto a connected iPhone or iPad without a Mac, and who is willing to work inside a browser tab that holds the signing credentials. It does not fit a team that needs a supported, audited signing pipeline, since the project is a single developer workspace with pre-built WebAssembly binaries and a relay in the middle, and it does not fit a device that is not connected over USB. Before adopting it, read the security posture of the hosted relay at sideload.nvme0n1p.dev before pointing it at your account, confirm your browser supports WebUSB, which in practice means a Chromium based browser, and check the AGENTS.md and the wasm/ build scripts if you intend to recompile the WebAssembly from source rather than use the prebuilt bundles.

## FAQ

### How do I run Side Impactor locally?

Run bun install --ignore-scripts and then bun run dev, and open http://localhost:5173. The dev script also performs setup, which updates the git submodules and prepares the WebAssembly dist bundles, and it starts the Cloudflare Worker on port 8787 alongside the frontend.

### Do I need to compile the WebAssembly components to use Side Impactor?

No. The build:wasm:dist script copies the prebuilt sources into the dist directories with no compiler needed, and the frontend production build runs it automatically. Recompiling from source with bun run build:wasm requires Rust, Emscripten and a precompiled OpenSSL.

### What is the Cloudflare Workers backend for?

The libcurl WASM build handles Apple API HTTP through a WISP proxy, because a browser page cannot make those cross-origin calls directly and needs a real TLS stack for pair record generation. The Workers relay is the component that carries that traffic.

### How do I run Side Impactor in Docker?

Run bun run build:wasm:dist first so the WebAssembly dists exist, then docker build -t sideload-web . and docker run -p 3000:3000 sideload-web. The image is a multi-stage build that serves the built frontend from nginx.

## Sources

- [Issues](https://github.com/lbr77/SideImpactor/issues)
- [lbr77/SideImpactor on GitHub](https://github.com/lbr77/SideImpactor)
- [License: MIT](https://github.com/lbr77/SideImpactor/blob/main/LICENSE)
- [Project website](https://sideload.nvme0n1p.dev)
- [README](https://github.com/lbr77/SideImpactor/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lbr77-sideimpactor
