Skip to content

fix(gateway): generate device user_code with a CSPRNG#159

Open
arseniycodes wants to merge 1 commit into
mainfrom
ash/sec-device-code-csprng
Open

fix(gateway): generate device user_code with a CSPRNG#159
arseniycodes wants to merge 1 commit into
mainfrom
ash/sec-device-code-csprng

Conversation

@arseniycodes

@arseniycodes arseniycodes commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Problem

The device-authorization user_code (humanCode()) was generated with Math.random() — a non-cryptographic PRNG — over an 8-character / 30-symbol alphabet. The user_code is the sole secret an approver verifies at /activate/approve.

Impact

Math.random()'s internal state is recoverable from observed outputs, so an attacker can predict in-flight user_codes within the code's TTL and call /activate/approve for a victim's pending device. Approval binds the attacker's org plus a freshly minted CLI session token and ingest key onto the victim's device session — silently redirecting the victim's CLI/telemetry into the attacker's project. (The device_code token pickup already used nanoid, so only the human-visible code was affected.)

Fix

Generate user_code with crypto.randomInt over the same alphabet (CSPRNG, unbiased).

Follow-up worth considering separately: rate-limit /activate/approve by IP/code. With a CSPRNG over ~30^8 the code space is now infeasible to brute-force, so this is defense-in-depth.


Summary by cubic

Generate the device-authorization user_code with a CSPRNG using crypto.randomInt to remove predictability. This prevents attackers from guessing in-flight codes and approving a victim’s device.

Written for commit aba7ab8. Summary will update on new commits.

Review in cubic

The device-authorization user_code was built from Math.random(), a
non-cryptographic PRNG, over an 8-char / 30-symbol alphabet. The
user_code is the only secret an approver checks at /activate/approve,
so a predictable generator lets an attacker who observes prior outputs
predict in-flight codes and approve a victim's pending device — binding
the attacker's org and a freshly minted session/ingest key onto the
victim's device.

Switch to crypto.randomInt over the same alphabet (unbiased, CSPRNG).

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Re-trigger cubic

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