Skip to content

fix(wizard): use Web Crypto (CSPRNG) for the gateway auth token#10

Open
kapelame wants to merge 1 commit into
microsofthackathons:mainfrom
kapelame:fix/wizard-gateway-token-csprng
Open

fix(wizard): use Web Crypto (CSPRNG) for the gateway auth token#10
kapelame wants to merge 1 commit into
microsofthackathons:mainfrom
kapelame:fix/wizard-gateway-token-csprng

Conversation

@kapelame
Copy link
Copy Markdown
Contributor

Description

The first-launch SetupWizard generates the OpenClaw Gateway auth token using `Math.random()`. `Math.random()` is a deterministic PRNG (V8 uses xorshift128+ with public algorithm) and is not safe to derive auth secrets from — given a few outputs, internal state can be recovered and subsequent outputs predicted.

This is also internally inconsistent with the installer's path:

Path Token generation
`deployer/windows_setup.py:1601` (Python installer) `secrets.token_hex(24)` — 192-bit CSPRNG ✓
`desktop/renderer/src/views/SetupWizard.vue:269` (first-launch wizard) `Math.random().toString(36).slice(2) + Date.now().toString(36)` — weak PRNG ✗

So the gateway's effective auth strength depends on which install path the user took, which is a real bug regardless of attacker model.

What the token actually protects

This isn't a throwaway request id — it's the bearer credential for the WebSocket handshake at `gateway-client.ts:305`:

```typescript
params.auth = { token: this.opts.token };
```

…and is read by `main.ts:1575` and used for every subsequent RPC. The OpenClaw Gateway exposes skill execution, file access, browser automation, and model invocation, so the token is real attack surface — local code (other user accounts on shared machines, or malware) that can fingerprint a few `Math.random()` outputs can predict the token and impersonate the desktop app to the local gateway.

Fix (one line)

```diff

  •  const token = Math.random().toString(36).slice(2) + Date.now().toString(36);
    
  •  // CSPRNG via Web Crypto — mirrors the installer's secrets.token_hex(24).
    
  •  // Math.random() is a deterministic PRNG and not safe for auth tokens.
    
  •  const token = crypto.randomUUID().replace(/-/g, "");
    

```

  • `crypto.randomUUID()` is Web Crypto API, CSPRNG-backed; available in Electron 33's Chromium 130 (and has been since Chromium 92).
  • Stripping the dashes yields a 32-char hex string, matching the installer's `secrets.token_hex(24)` output format so the two install paths produce structurally identical config.
  • Convention is already established in this repo: `desktop/src/gateway-client.ts:13` imports Node's `randomUUID`, `desktop/studio-backend/src/store.js:104` uses `crypto.randomUUID()`, and `plugins/openclaw-weixin/src/auth/login-qr.ts` uses Node CSPRNG.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature
  • Breaking change
  • Documentation update
  • CI/CD or build configuration change
  • Refactoring

Testing

  • Renderer tests pass locally (`cd desktop/renderer && npm run test`) — 8 files / 139 tests, all green
  • Prettier on the touched file — clean
  • ESLint on the touched file — pre-existing warnings only (lines 57, 227, 282), none on the changed lines (267–272); zero new warnings introduced
  • Build (`cd desktop && npm run build`) — not run locally (no Windows toolchain on this dev machine); the project's `pr-build.yml` Windows self-hosted runner will gate
  • Manual reasoning: `crypto.randomUUID()` returns a string (no API shape change for the consumer), and the consumer (`auth.token`) only uses the value as an opaque bearer string. Functionally indistinguishable from the previous behavior except for entropy.

Compatibility

  • Backward compatible: existing `openclaw.json` files that already have `gateway.auth.token` aren't touched (the wizard only runs the token-generation branch when `!existing.gateway`).
  • New tokens generated under this patch are the same length and shape as the installer's tokens, so any downstream code that grepped for token shape continues to work.

Checklist

  • Code follows existing patterns (other files in the same repo already use `crypto.randomUUID()` / Node CSPRNG)
  • Self-review performed
  • No new comments needed beyond the two-line rationale comment added at the change site
  • No documentation changes — this is a behavioral fix, not a user-facing API change
  • No new warnings introduced
  • No new tests added — the change is a 1-call replacement; behavior is "produce an opaque token string" both before and after; existing tests already exercise the surrounding flow
  • Existing unit tests pass locally with the change applied

SetupWizard generates the gateway auth token with
'Math.random().toString(36).slice(2) + Date.now().toString(36)'.
Math.random() is a deterministic PRNG (V8 uses xorshift128+) and is
not safe to derive auth secrets from — given a few outputs, the
internal state can be recovered and subsequent outputs predicted.

The Python installer at deployer/windows_setup.py:1601 already uses
secrets.token_hex(24), so depending on which install path the user
took the gateway ends up with very different token strength. This
patch aligns the wizard path with the installer using crypto
.randomUUID() (Web Crypto, CSPRNG) and strips the dashes so the
output format matches the installer's hex string.

The token is the bearer credential for the WebSocket handshake to
the local OpenClaw Gateway (gateway-client.ts:305) and gates every
RPC the desktop app issues, so the underlying entropy matters.
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.

1 participant