cxpher 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -60
- package/cli-wrapper.cjs +9 -6
- package/install.cjs +10 -5
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -21,17 +21,17 @@ The safest way to ship JavaScript. Full stop. The only JavaScript toolchain that
|
|
|
21
21
|
|
|
22
22
|
cXpher is a complete JavaScript toolchain that does what no other tool on the market does: it takes your JavaScript or TypeScript project, bundles it, encrypts the source, generates a native binary with the encrypted payload embedded inside, and compiles it into a single executable wrapped in a defense-in-depth runtime envelope. **Your source code never reaches disk at runtime, your binary refuses to run under debuggers, and every build is cryptographically unique.**
|
|
23
23
|
|
|
24
|
-
It is also a fully functional package manager with dependency resolution, a global content-addressable store, lockfile management, and parallel installation
|
|
24
|
+
It is also a fully functional package manager with dependency resolution, a global content-addressable store, lockfile management, and parallel installation - competing directly with npm, yarn, pnpm, and bun on the package management side, while offering a compilation pipeline that none of them have and a security posture none of them attempt.
|
|
25
25
|
|
|
26
|
-
Output is a single native binary for the OS / arch of your choice
|
|
26
|
+
Output is a single native binary for the OS / arch of your choice - **Linux, macOS, Windows, x64, x86, ARM64 or ARM32** - produced from any Node-compatible JavaScript or TypeScript source. A single `cxpher compile-all` produces every binary plus a generated Node CLI wrapper into `dist/` in one pass. Scripts in your `package.json` run with a single command (`cxpher <script>`, yarn-style), and the interactive surface is a clack-prompts-style flow with select menus, validated text inputs, and a clean two-accent palette.
|
|
27
27
|
|
|
28
28
|
## Why cXpher Exists
|
|
29
29
|
|
|
30
|
-
Every JavaScript bundler on the market produces readable output. Minification is obfuscation theatre
|
|
30
|
+
Every JavaScript bundler on the market produces readable output. Minification is obfuscation theatre - any competent engineer can reverse it in an afternoon. Bytecode compilation (V8 snapshots, Bun's bytecode) is equally reversible with widely available decompilers. Even tools that produce "binaries" (pkg, nexe, bun --compile) embed the source as plaintext or trivially-decompiled bytecode inside the executable.
|
|
31
31
|
|
|
32
|
-
If you're shipping a commercial Node.js application, a proprietary CLI tool, a paid API server, or an internal enterprise tool, **with every other toolchain on the market, your source code is exposed.** There is currently no production-grade JavaScript packaging solution that takes source protection seriously
|
|
32
|
+
If you're shipping a commercial Node.js application, a proprietary CLI tool, a paid API server, or an internal enterprise tool, **with every other toolchain on the market, your source code is exposed.** There is currently no production-grade JavaScript packaging solution that takes source protection seriously - except cXpher.
|
|
33
33
|
|
|
34
|
-
cXpher doesn't obfuscate. It doesn't minify and hope. It encrypts with modern symmetric crypto, hardens the runtime against debuggers, removes the disk surface entirely, randomises every component of every build, and wraps the result in a binary that requires real reverse-engineering effort to crack. **Software-only protection has a mathematical ceiling
|
|
34
|
+
cXpher doesn't obfuscate. It doesn't minify and hope. It encrypts with modern symmetric crypto, hardens the runtime against debuggers, removes the disk surface entirely, randomises every component of every build, and wraps the result in a binary that requires real reverse-engineering effort to crack. **Software-only protection has a mathematical ceiling - but cXpher pushes that ceiling as high as it will go.**
|
|
35
35
|
|
|
36
36
|
## The Safest Package Manager Built for JavaScript
|
|
37
37
|
|
|
@@ -49,7 +49,7 @@ cXpher is the only JavaScript toolchain that combines a full package manager wit
|
|
|
49
49
|
|
|
50
50
|
**At runtime:**
|
|
51
51
|
|
|
52
|
-
- **Zero-disk source delivery.** The primary execution path streams decrypted source directly into the JavaScript interpreter through an in-memory channel. No filesystem entry is ever created in the primary path
|
|
52
|
+
- **Zero-disk source delivery.** The primary execution path streams decrypted source directly into the JavaScript interpreter through an in-memory channel. No filesystem entry is ever created in the primary path - your source has no path on the disk, no entry in process listings, no name to grep for.
|
|
53
53
|
- **Native debugger-resistance on every platform.** Linux, macOS, and Windows each ship platform-specific runtime checks that detect debugger attachment and exit silently. The exits are silent on purpose: an attacker cannot learn which check fired or what triggered it.
|
|
54
54
|
- **Timing-attack detection.** The runtime self-monitors execution timing against a tight budget. Single-step debugging blows the budget and the process exits silently within milliseconds.
|
|
55
55
|
- **Key material never exists whole.** The encryption key is reconstructed inside the running process only at the moment of decryption, wiped immediately after use, and never appears as a contiguous byte sequence anywhere in the binary's data sections.
|
|
@@ -59,13 +59,13 @@ cXpher is the only JavaScript toolchain that combines a full package manager wit
|
|
|
59
59
|
**At distribution time:**
|
|
60
60
|
|
|
61
61
|
- One command (`cxpher compile-all`) produces native binaries for **every supported platform and architecture in a single pass**, plus a generated Node wrapper that auto-selects the right binary at install time. Ship the entire matrix as one npm package.
|
|
62
|
-
- Compile cache disabled by default
|
|
62
|
+
- Compile cache disabled by default - `--cache` is opt-in. Every fresh build is a clean build with new key material unless you explicitly opt back in.
|
|
63
63
|
|
|
64
64
|
### What this means in practice
|
|
65
65
|
|
|
66
|
-
A determined reverse engineer with significant time and the right tooling can eventually defeat any software-only protection. That's not specific to cXpher, that's the mathematical floor of running encrypted code on hardware you don't control. What cXpher does is **push the cost of extraction from "five minutes with a tutorial" to "one to two weeks of dedicated, skilled reverse engineering effort"**
|
|
66
|
+
A determined reverse engineer with significant time and the right tooling can eventually defeat any software-only protection. That's not specific to cXpher, that's the mathematical floor of running encrypted code on hardware you don't control. What cXpher does is **push the cost of extraction from "five minutes with a tutorial" to "one to two weeks of dedicated, skilled reverse engineering effort"** - which rules out 99.9% of would-be attackers, leaves only adversaries with serious budget and intent, and protects against every realistic threat short of a nation-state.
|
|
67
67
|
|
|
68
|
-
For the remaining cases
|
|
68
|
+
For the remaining cases - where you need a hard floor against any conceivable attacker - cXpher is the strongest building block. Combine it with server-side key fetch, hardware TEE (SGX, TrustZone, Secure Enclave), or licensed runtime checks and you have a protection model nothing in the JavaScript ecosystem can match.
|
|
69
69
|
|
|
70
70
|
## How the Pipeline Works (High Level)
|
|
71
71
|
|
|
@@ -74,7 +74,7 @@ The compilation flow has four high-level stages:
|
|
|
74
74
|
1. **Bundle.** Detect your project's entry point and bundle all source files and `node_modules` into a single JavaScript blob. Self-contained, zero external requirements.
|
|
75
75
|
2. **Encrypt + randomise.** The bundle is wrapped with an argv-forwarding shim and encrypted with per-build random keying material. The key is decomposed across the binary in a layout that's different for every build.
|
|
76
76
|
3. **Generate C runtime.** A platform-specific runtime stub is generated, containing the encrypted payload, the key reconstruction logic, the anti-tampering checks, and the in-memory source delivery channel. The stub is compiled into the final binary with full optimizations.
|
|
77
|
-
4. **Compile to native binary.** GCC, Clang, MinGW, or MSVC produces a standard ELF (Linux), Mach-O (macOS), or PE (Windows) executable. The binary is fully self-contained
|
|
77
|
+
4. **Compile to native binary.** GCC, Clang, MinGW, or MSVC produces a standard ELF (Linux), Mach-O (macOS), or PE (Windows) executable. The binary is fully self-contained - no runtime dependency on OpenSSL, libcrypto, or any other shared library beyond libc.
|
|
78
78
|
|
|
79
79
|
The runtime stub's internal mechanics are intentionally not enumerated. They are designed to be effective, not catalogued for would-be attackers. What matters externally: the binary runs anywhere the target platform's libc runs, your source never reaches disk, and your binary refuses to run under inspection.
|
|
80
80
|
|
|
@@ -116,9 +116,9 @@ The SEA path runs the same protection stack as the standard path, plus eliminate
|
|
|
116
116
|
|
|
117
117
|
### Why not just use Bun's `--compile`?
|
|
118
118
|
|
|
119
|
-
Bun's compile flag produces a binary that contains JavaScriptCore bytecode. Bytecode is not source protection
|
|
119
|
+
Bun's compile flag produces a binary that contains JavaScriptCore bytecode. Bytecode is not source protection - it is a performance optimization. Decompilers for JS bytecode exist and are actively maintained. The original source structure, variable names, and logic are recoverable in minutes by anyone with the right tool.
|
|
120
120
|
|
|
121
|
-
cXpher ships a fundamentally different class of artifact: a compiled native binary with encrypted source, per-build randomised key material that never exists whole on disk, runtime debugger detection, timing-attack defences, and a delivery channel to Node that never touches the filesystem. Recovering source from an cXpher binary requires real reverse-engineering against a hardened runtime
|
|
121
|
+
cXpher ships a fundamentally different class of artifact: a compiled native binary with encrypted source, per-build randomised key material that never exists whole on disk, runtime debugger detection, timing-attack defences, and a delivery channel to Node that never touches the filesystem. Recovering source from an cXpher binary requires real reverse-engineering against a hardened runtime - typically days to weeks of dedicated effort by a skilled adversary, not minutes with a decompiler.
|
|
122
122
|
|
|
123
123
|
### Why not pkg or nexe?
|
|
124
124
|
|
|
@@ -153,35 +153,35 @@ cxpher test
|
|
|
153
153
|
cxpher dev
|
|
154
154
|
|
|
155
155
|
# Build (runs your build script)
|
|
156
|
-
|
|
156
|
+
cx build
|
|
157
157
|
|
|
158
158
|
# Compile to encrypted native binary
|
|
159
|
-
|
|
159
|
+
cx compile
|
|
160
160
|
|
|
161
161
|
# Compile to standalone binary (embeds Node.js)
|
|
162
|
-
|
|
162
|
+
cX compile --standalone
|
|
163
163
|
|
|
164
164
|
# Cross-compile to a 32-bit Windows machine
|
|
165
|
-
|
|
165
|
+
cX compile -w32
|
|
166
166
|
|
|
167
167
|
# Or target a specific OS / arch combo
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
cXpher compile --target linux-x86
|
|
169
|
+
cXpher compile --target win-arm64
|
|
170
170
|
|
|
171
171
|
# Build every binary plus a CLI wrapper into dist/ in one shot
|
|
172
|
-
|
|
172
|
+
cx compile-all
|
|
173
173
|
|
|
174
174
|
# Same, plus ARM64 + ARM32 for linux and win (8 total)
|
|
175
|
-
|
|
175
|
+
cx compile-all --arm
|
|
176
176
|
|
|
177
177
|
# Just refresh the dist/cli.js wrapper, no binaries
|
|
178
|
-
|
|
178
|
+
cX compile-all --cli-only
|
|
179
179
|
|
|
180
180
|
# Add a local package (no npm round-trip, ever)
|
|
181
|
-
|
|
181
|
+
cXpher add ./packages/shared
|
|
182
182
|
cxpher add file:../sibling-pkg
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
cx add link:./local-dev-pkg # symlink instead of hardlink
|
|
184
|
+
cX add myname@file:./other-package # explicit alias
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
## Commands
|
|
@@ -197,7 +197,7 @@ cxpher add myname@file:./other-package # explicit alias
|
|
|
197
197
|
| `cxpher add <pkg>` | Add a registry dependency (npm → yarn → jsr → github fallback chain) |
|
|
198
198
|
| `cxpher add -D <pkg>` | Add a dev dependency |
|
|
199
199
|
| `cxpher add <path>` | Add a **local** package by relative or absolute path (no registry round-trip) |
|
|
200
|
-
| `cxpher add file:<path>` | Same as above, explicit protocol
|
|
200
|
+
| `cxpher add file:<path>` | Same as above, explicit protocol - hardlinks the package tree into `node_modules/` |
|
|
201
201
|
| `cxpher add link:<path>` | Symlink the local package into `node_modules/` instead of hardlinking. Live edits picked up instantly. |
|
|
202
202
|
| `cxpher add portal:<path>` | Alias of `link:` |
|
|
203
203
|
| `cxpher add <name>@file:<path>` | Local install under an explicit dependency name |
|
|
@@ -232,7 +232,7 @@ cxpher add myname@file:./other-package # explicit alias
|
|
|
232
232
|
| `-l` / `-w` / `-m` | Shorthand: Linux / Windows / macOS (defaults to `x64`) |
|
|
233
233
|
| `-l32` / `-w32` / `-m32` | Shorthand: 32-bit (`x86`) Linux / Windows / macOS |
|
|
234
234
|
| `-l64` / `-w64` / `-m64` | Explicit 64-bit shorthand - aliases of `-l` / `-w` / `-m` |
|
|
235
|
-
| `--arm` | ARM target. Defaults to `arm64
|
|
235
|
+
| `--arm` | ARM target. Defaults to `arm64`. Combine with `-l` / `-w` for cross-compile. |
|
|
236
236
|
| `--arm64` / `--arm32` | Explicit ARM 64-bit or 32-bit. |
|
|
237
237
|
| `--arch <arch>` | Target architecture independently of `--target`. Accepts `x64` (default), `x86`, `arm64`, `arm32`, plus aliases (`ia32`, `i386`, `i686`, `amd64`, `x86_64`, `aarch64`, `armv7`, `armv7l`, `armhf`, `arm`). |
|
|
238
238
|
| `--minify` | Minify source before encryption |
|
|
@@ -341,9 +341,9 @@ cXpher hashes your source tree before compilation. If the hash matches a previou
|
|
|
341
341
|
|
|
342
342
|
`cxpher add` skips the registry entirely when given a local path. The package's own `package.json` is read off disk to pull the name, version, and transitive dependencies, and the resulting tree entry is marked `local: true` so the installer takes the local-install path. Three protocols are recognised:
|
|
343
343
|
|
|
344
|
-
- **`file:`**
|
|
345
|
-
- **`link:`**
|
|
346
|
-
- **`portal:`**
|
|
344
|
+
- **`file:`** - copy/hardlink the local package tree into `node_modules/`. Default for bare paths (`./pkg`, `../sibling`, `/abs/path`, `~/lib`).
|
|
345
|
+
- **`link:`** - create a directory symlink instead. Live edits to the source pick up immediately. Equivalent to `npm link` / `yarn link` but scoped to a single dependency.
|
|
346
|
+
- **`portal:`** - alias of `link:`.
|
|
347
347
|
|
|
348
348
|
The local install hardlink skips the source package's own `node_modules/`, `.git/`, and `.cxpher-stored` markers so consumers don't recurse into the dependency's dependency tree.
|
|
349
349
|
|
|
@@ -352,11 +352,11 @@ The local install hardlink skips the source package's own `node_modules/`, `.git
|
|
|
352
352
|
`fetchPackument` walks an ordered list of registries on every lookup and short-circuits on the first 200. Default chain:
|
|
353
353
|
|
|
354
354
|
1. `https://registry.npmjs.org` (npm)
|
|
355
|
-
2. `https://registry.yarnpkg.com` (yarn
|
|
356
|
-
3. `https://npm.jsr.io` (jsr
|
|
355
|
+
2. `https://registry.yarnpkg.com` (yarn - npm mirror with different caching)
|
|
356
|
+
3. `https://npm.jsr.io` (jsr - the JS Registry)
|
|
357
357
|
4. `https://npm.pkg.github.com` (github packages)
|
|
358
358
|
|
|
359
|
-
404 / 401 / 403 from any registry is treated as "not here, try the next one"
|
|
359
|
+
404 / 401 / 403 from any registry is treated as "not here, try the next one" - the chain only throws when every registry has rejected the name. A 200 response is cached against the package name (not the registry), so subsequent lookups hit the cache regardless of which registry served the packument.
|
|
360
360
|
|
|
361
361
|
Override the chain via `~/.cxpher/config.json`:
|
|
362
362
|
|
|
@@ -376,13 +376,13 @@ Override the chain via `~/.cxpher/config.json`:
|
|
|
376
376
|
|
|
377
377
|
### `compile-all` and the Generated CLI Wrapper
|
|
378
378
|
|
|
379
|
-
`compile-all` produces every binary plus a generated Node script (`dist/cli.js`) in a single pass. The wrapper detects `process.platform` and `process.arch` at runtime and execs the matching binary out of the same directory
|
|
379
|
+
`compile-all` produces every binary plus a generated Node script (`dist/cli.js`) in a single pass. The wrapper detects `process.platform` and `process.arch` at runtime and execs the matching binary out of the same directory - install one npm package that ships all four (or eight with `--arm`) binaries plus the wrapper as the `bin` entry, and the right binary runs on every platform the user installs it on.
|
|
380
380
|
|
|
381
381
|
When `dist/` already exists, a select prompt asks (the same prompt is shared with `cxpher compiler`):
|
|
382
382
|
|
|
383
|
-
- **Install alongside existing files**
|
|
384
|
-
- **Backup current dist**
|
|
385
|
-
- **Wipe and start fresh**
|
|
383
|
+
- **Install alongside existing files** - overwrite only the targets being built and leave everything else in `dist/` untouched.
|
|
384
|
+
- **Backup current dist** - copies `dist/` to the next free `dist_backup_NNN/` (zero-padded 3-digit, based on the highest existing number in the project root), then wipes `dist/` and continues. Default.
|
|
385
|
+
- **Wipe and start fresh** - removes `dist/` without a backup.
|
|
386
386
|
|
|
387
387
|
`--cli-only` skips every binary and just (re)writes `dist/cli.js`. Useful for refreshing the wrapper after a package rename without rebuilding everything.
|
|
388
388
|
|
|
@@ -405,19 +405,19 @@ Any unsupported platform/arch combination throws a clear `Unsupported platform:`
|
|
|
405
405
|
|
|
406
406
|
Before any binary is built, `compile-all` runs a toolchain preflight check against every requested target. If any cross-compilers are missing, you get a three-way prompt:
|
|
407
407
|
|
|
408
|
-
- **Install missing toolchains and build all**
|
|
409
|
-
- **Skip missing targets, build the rest**
|
|
410
|
-
- **Abort**
|
|
408
|
+
- **Install missing toolchains and build all** - calls `install-toolchain` for the missing targets, then continues.
|
|
409
|
+
- **Skip missing targets, build the rest** - drops the targets whose toolchains aren't available and carries on with the ones that are.
|
|
410
|
+
- **Abort** - does nothing.
|
|
411
411
|
|
|
412
412
|
`--yes` / `-y` auto-picks install. Individual compile failures during the loop are warned-and-skipped rather than fatal, so one bad target never kills the rest of the batch.
|
|
413
413
|
|
|
414
|
-
### `install-toolchain`
|
|
414
|
+
### `install-toolchain` - auto-install cross-compilers
|
|
415
415
|
|
|
416
416
|
`cxpher install-toolchain` detects the host OS, distro and package manager and installs the cross-compilers required for any compile target. Supported package managers:
|
|
417
417
|
|
|
418
418
|
| OS / Distro | Manager | Notes |
|
|
419
419
|
|-------------|---------|-------|
|
|
420
|
-
| Arch / Manjaro / EndeavourOS | `pacman` + `yay` / `paru` | Repo packages via pacman with sudo
|
|
420
|
+
| Arch / Manjaro / EndeavourOS | `pacman` + `yay` / `paru` | Repo packages via pacman with sudo. AUR / chaotic-aur via yay/paru without sudo |
|
|
421
421
|
| Debian / Ubuntu | `apt-get` | sudo |
|
|
422
422
|
| Fedora / RHEL / CentOS | `dnf` | sudo |
|
|
423
423
|
| openSUSE | `zypper` | sudo |
|
|
@@ -427,13 +427,13 @@ Before any binary is built, `compile-all` runs a toolchain preflight check again
|
|
|
427
427
|
|
|
428
428
|
Invocations:
|
|
429
429
|
|
|
430
|
-
- `cxpher install-toolchain`
|
|
431
|
-
- `cxpher install-toolchain --all`
|
|
432
|
-
- `cxpher install-toolchain --arm`
|
|
433
|
-
- `cxpher install-toolchain --x86`
|
|
434
|
-
- `cxpher install-toolchain --win` / `--linux`
|
|
435
|
-
- `cxpher install-toolchain linux-arm32 win-x86 ...`
|
|
436
|
-
- `cxpher install-toolchain --yes`
|
|
430
|
+
- `cxpher install-toolchain` - interactive. Lists every target with installed/missing flags, multiselect to pick what to install.
|
|
431
|
+
- `cxpher install-toolchain --all` - install every cross-compiler cxpher knows about.
|
|
432
|
+
- `cxpher install-toolchain --arm` - install only ARM (linux/win × arm64/arm32).
|
|
433
|
+
- `cxpher install-toolchain --x86` - install only 32-bit x86 (linux + win).
|
|
434
|
+
- `cxpher install-toolchain --win` / `--linux` - install all cross-compilers for that OS.
|
|
435
|
+
- `cxpher install-toolchain linux-arm32 win-x86 ...` - install only the named targets.
|
|
436
|
+
- `cxpher install-toolchain --yes` - skip the confirm prompt.
|
|
437
437
|
|
|
438
438
|
Targets with no native package on the current distro (Windows ARM on debian/fedora, macOS cross from anything) are reported with a manual-install link rather than silently skipped.
|
|
439
439
|
|
|
@@ -441,15 +441,15 @@ Targets with no native package on the current distro (Windows ARM on debian/fedo
|
|
|
441
441
|
|
|
442
442
|
Each target carries an ordered list of install steps. The installer walks the chain in order, verifies after each attempt, and only moves on if the current step fails or installs without putting the expected binary on PATH. Example: `linux-arm32` on Arch tries
|
|
443
443
|
|
|
444
|
-
1. **Linaro precompiled binary** (`arm-linux-gnueabihf-gcc13-linaro-bin` from AUR)
|
|
445
|
-
2. **Official ARM GNU toolchain**
|
|
446
|
-
3. **Build from source** (`arm-linux-gnueabihf-gcc` from AUR)
|
|
444
|
+
1. **Linaro precompiled binary** (`arm-linux-gnueabihf-gcc13-linaro-bin` from AUR) - fast, but depends on snapshots.linaro.org being reachable.
|
|
445
|
+
2. **Official ARM GNU toolchain** - downloads the `arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz` archive from developer.arm.com, extracts to `/opt/cxpher-toolchains/arm-none-linux-gnueabihf/`, and symlinks both the Arm-official names (`arm-none-linux-gnueabihf-*`) and the standard names (`arm-linux-gnueabihf-*`) into `/usr/local/bin/`. Reusable for `linux-arm64` (triplet `aarch64-none-linux-gnu`) as well.
|
|
446
|
+
3. **Build from source** (`arm-linux-gnueabihf-gcc` from AUR) - last resort, takes 1-2 hours.
|
|
447
447
|
|
|
448
448
|
Failed steps print a one-line reason and the chain continues. If every step fails the target is reported as still-missing in the final status section.
|
|
449
449
|
|
|
450
450
|
#### macOS native targets
|
|
451
451
|
|
|
452
|
-
On a macOS host, `darwin-x64` and `darwin-arm64` are detected as installed when native `clang` plus `xcode-select -p` both resolve
|
|
452
|
+
On a macOS host, `darwin-x64` and `darwin-arm64` are detected as installed when native `clang` plus `xcode-select -p` both resolve - those are the prerequisites for `clang -arch x86_64` and `clang -arch arm64` native compiles. The `darwin-x64` / `darwin-arm64` install step on a macOS host calls `xcode-select --install` to trigger Apple's GUI installer for the Command Line Tools. From a Linux host, the same targets fall back to a `manual` osxcross install step (no automated install path exists for osxcross - it requires the Xcode SDK which can't be redistributed). Apple dropped 32-bit Intel and 32-bit ARM support in macOS Catalina (10.15), so no `darwin-x86` or `darwin-arm32` target exists.
|
|
453
453
|
|
|
454
454
|
#### `llvm-mingw` post-install symlink hook
|
|
455
455
|
|
|
@@ -457,18 +457,18 @@ On Arch, `llvm-mingw` from chaotic-aur / AUR installs into `/opt/llvm-mingw/bin/
|
|
|
457
457
|
|
|
458
458
|
## Security Model
|
|
459
459
|
|
|
460
|
-
cXpher is the strongest software-only source protection in the JavaScript ecosystem. It is not a DRM system
|
|
460
|
+
cXpher is the strongest software-only source protection in the JavaScript ecosystem. It is not a DRM system - pure software protection has a theoretical floor that nothing can move without external trust (server-fetched keys or hardware TEE) - but it pushes that floor as high as it goes.
|
|
461
461
|
|
|
462
462
|
**What cXpher protects against:**
|
|
463
463
|
|
|
464
464
|
- Direct source code reading from the distributed binary.
|
|
465
465
|
- Trivial decompilation (the entire class of attack that defeats every other JS packager).
|
|
466
466
|
- Casual filesystem extraction during runtime (your source never reaches the disk in the primary execution path).
|
|
467
|
-
- Common debugger inspection
|
|
468
|
-
- Single-step debugging
|
|
469
|
-
- Bulk extraction across versions
|
|
467
|
+
- Common debugger inspection - Linux, macOS, and Windows binaries refuse to run when a debugger is attached and exit silently.
|
|
468
|
+
- Single-step debugging - runtime timing checks detect single-stepping and silently exit within milliseconds.
|
|
469
|
+
- Bulk extraction across versions - every build is cryptographically independent.
|
|
470
470
|
- Casual copying of proprietary logic by employees, customers, or anyone with the binary but without serious tooling.
|
|
471
|
-
- Source exposure in containerised, cloud, or shared-filesystem deployments
|
|
471
|
+
- Source exposure in containerised, cloud, or shared-filesystem deployments - there is no source file to expose.
|
|
472
472
|
|
|
473
473
|
**What cXpher does not protect against:**
|
|
474
474
|
|
|
@@ -476,9 +476,9 @@ cXpher is the strongest software-only source protection in the JavaScript ecosys
|
|
|
476
476
|
- Runtime memory inspection performed at the kernel level by an attacker with root access on the host.
|
|
477
477
|
- Hardware-level memory dumps from a cold-boot or DMA attack.
|
|
478
478
|
|
|
479
|
-
For the realistic threat model
|
|
479
|
+
For the realistic threat model - protecting commercial JavaScript IP against employees, customers, competitors, security researchers without unlimited budget, and the entire long tail of opportunistic extraction attempts - **cXpher is the strongest answer the JavaScript ecosystem has.**
|
|
480
480
|
|
|
481
|
-
This is the same security model as any compiled C, C++, Go, or Rust application
|
|
481
|
+
This is the same security model as any compiled C, C++, Go, or Rust application - but with the added per-build-randomised, debugger-aware, disk-free runtime envelope that no other JavaScript packager attempts.
|
|
482
482
|
|
|
483
483
|
## System Requirements
|
|
484
484
|
|
|
@@ -503,7 +503,7 @@ This is the same security model as any compiled C, C++, Go, or Rust application
|
|
|
503
503
|
| Windows ARM32 | ✓ ² | - | ✓ (via `armv7-w64-mingw32-clang`) |
|
|
504
504
|
|
|
505
505
|
<sup>¹ Standalone (`--standalone`) embeds the host Node.js binary, and Node has not shipped 32-bit Linux or 32-bit ARM builds for years. For these targets use the default encrypted-binary path - it cross-compiles cleanly via the system C toolchain.</sup>
|
|
506
|
-
<sup>² Windows ARM requires the [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain
|
|
506
|
+
<sup>² Windows ARM requires the [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain. The default MinGW packages from most distros only ship x86_64 / i686 targets.</sup>
|
|
507
507
|
|
|
508
508
|
## License
|
|
509
509
|
|
package/cli-wrapper.cjs
CHANGED
|
@@ -10,14 +10,17 @@
|
|
|
10
10
|
|
|
11
11
|
* © Agentics (Pty) Ltd - All Rights Reserved
|
|
12
12
|
* https://agentics.co.za <-> info@agentics.co.za
|
|
13
|
-
*/
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
* Fallback launcher for cxpher.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
* Normally install.cjs (postinstall) copies the native binary over
|
|
19
|
+
* bin/<brand>.exe, so this file is never invoked. It exists for environments
|
|
20
|
+
* where postinstall doesn't run (--ignore-scripts) — pay the Node-process
|
|
21
|
+
* overhead and forward to the native binary anyway.
|
|
22
|
+
|
|
23
|
+
*/
|
|
21
24
|
|
|
22
25
|
const { spawnSync } = require('child_process');
|
|
23
26
|
const { arch, constants } = require('os');
|
package/install.cjs
CHANGED
|
@@ -10,13 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
* © Agentics (Pty) Ltd - All Rights Reserved
|
|
12
12
|
* https://agentics.co.za <-> info@agentics.co.za
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
* Postinstall for cxpher.
|
|
17
|
+
|
|
18
|
+
* binary from the matching optional-dependency subpackage. After this runs,
|
|
19
|
+
* invocations of `cxpher` (and aliases) exec the native binary directly on
|
|
20
|
+
* Unix. The fallback launcher logic stays inside bin/cXpher.js itself in
|
|
21
|
+
* case postinstall is skipped (--ignore-scripts).
|
|
22
|
+
|
|
13
23
|
*/
|
|
14
24
|
|
|
15
|
-
// Postinstall for cxpher: replace bin/cXpher.js placeholder with the native
|
|
16
|
-
// binary from the matching optional-dependency subpackage. After this runs,
|
|
17
|
-
// invocations of `cxpher` (and aliases) exec the native binary directly on
|
|
18
|
-
// Unix. The fallback launcher logic stays inside bin/cXpher.js itself in
|
|
19
|
-
// case postinstall is skipped (--ignore-scripts).
|
|
20
25
|
|
|
21
26
|
const { spawnSync } = require('child_process');
|
|
22
27
|
const { copyFileSync, linkSync, unlinkSync, chmodSync, mkdirSync } = require('fs');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cxpher",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agentics Package Manager — Encrypted native binary compiler + package manager for JavaScript",
|
|
6
6
|
"main": "bin/cXpher.js",
|
|
@@ -50,15 +50,15 @@
|
|
|
50
50
|
"author": "Connor Etherington <connor@agentics.co.za>",
|
|
51
51
|
"license": "MIT",
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"cxpher-darwin-arm64": "2.0.
|
|
54
|
-
"cxpher-darwin-x64": "2.0.
|
|
55
|
-
"cxpher-linux-arm32": "2.0.
|
|
56
|
-
"cxpher-linux-arm64": "2.0.
|
|
57
|
-
"cxpher-linux-x64": "2.0.
|
|
58
|
-
"cxpher-linux-x86": "2.0.
|
|
59
|
-
"cxpher-win-arm32": "2.0.
|
|
60
|
-
"cxpher-win-arm64": "2.0.
|
|
61
|
-
"cxpher-win-x64": "2.0.
|
|
62
|
-
"cxpher-win-x86": "2.0.
|
|
53
|
+
"cxpher-darwin-arm64": "2.0.2",
|
|
54
|
+
"cxpher-darwin-x64": "2.0.2",
|
|
55
|
+
"cxpher-linux-arm32": "2.0.2",
|
|
56
|
+
"cxpher-linux-arm64": "2.0.2",
|
|
57
|
+
"cxpher-linux-x64": "2.0.2",
|
|
58
|
+
"cxpher-linux-x86": "2.0.2",
|
|
59
|
+
"cxpher-win-arm32": "2.0.2",
|
|
60
|
+
"cxpher-win-arm64": "2.0.2",
|
|
61
|
+
"cxpher-win-x64": "2.0.2",
|
|
62
|
+
"cxpher-win-x86": "2.0.2"
|
|
63
63
|
}
|
|
64
64
|
}
|