Skip to content

[core] Fix vulnerable nanoid pin by dropping the dependency - #4335

Merged
pranaygp merged 4 commits into
mainfrom
triage-workflow3842-hardcoded-dep-version
Oct 14, 2026
Merged

pranaygp merged 4 commits into
mainfrom
triage-workflow3842-hardcoded-dep-version

Conversation

@pranaygp

@pranaygp pranaygp commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3842.

What

@workflow/core pins nanoid exactly at 5.1.6, which is in the vulnerable range of GHSA-28wg-ghj8-5hjv (high, >=4.0.0 <5.1.16). Because the pin is exact, apps can only move off it with an overrides/resolutions entry.

This PR removes the dependency instead of bumping it.

Why not just bump nanoid?

Core uses nanoid only to build the seeded generator for default hook tokens: customRandom(urlAlphabet, 21, bytes from the run-seeded PRNG). In 5.1.16, customRandom requests 21 bytes per id instead of 34. For the same seed, that changes both the hook token and every seeded value drawn after it (Math.random() inside the workflow, later tokens):

seed wrun_test:seed 1st token 2nd token next Math.random()
nanoid 5.1.6 pVjvQyygUGbIid9mUBIhp mgNKWnMBr9yywfW_syBGT 0.3399…
nanoid 5.1.16 d9mUBIhphoZLwZ1T1ma-k jdT3d6rupVjvQyygUGbIi 0.1769…

A run recorded before the upgrade and replayed after it would diverge. On stable, a plain bump failed the hook-sleep-interaction replay tests with ReplayDivergenceError (see #4336's history). The same applies to users who add a nanoid override today.

Changes

  • packages/core/src/seeded-nanoid.ts reproduces nanoid 5.1.6's customRandom(urlAlphabet, 21, ...) exactly: 34 draws per id, read from the end of the batch.
  • seeded-nanoid.test.ts pins the recorded 5.1.6 output and PRNG position, so any change to the draw pattern fails a test.
  • The node:vm engine (workflow.ts), the QuickJS engine (runtime/quickjs-runtime.ts) and the test helpers all use it.
  • nanoid is removed from @workflow/core's dependencies.
  • The two private Next.js workbenches, which use nanoid directly, are bumped to 5.1.16.
  • Changeset: patch for @workflow/core, worded as a security fix so the backport check picks it up.

Verification

  • pnpm --filter @workflow/core test passes (3070 tests on current main), and typecheck passes.
  • Installing this PR's workflow-tarballs build and running npm audit --omit=dev reports 0 vulnerabilities, with no nanoid in the tree.

Related

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d8bd20c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/web Patch
workflow Patch
@workflow/world-testing Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch
@workflow/world-vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
example-nextjs-workflow-turbopack Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
example-nextjs-workflow-webpack Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
example-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-astro-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-express-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-fastify-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-hono-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-nestjs-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-nitro-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-nuxt-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-python-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-sveltekit-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-tanstack-start-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workbench-vite-workflow Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workflow-docs Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workflow-swc-playground Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workflow-tarballs Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC
workflow-web Ready Ready Preview, v0 Oct 14, 2026 12:28am UTC

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

✅ All tests passed

⚠️ Flaky E2E Tests (passed on retry)

These tests failed at least once and passed on a retry. A recurring entry here is a real race worth investigating.

  • abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries (nextjs-webpack · local-dev / local / node / canary)
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously (nuxt · local-dev / local / node / stable)
  • fire-and-forget: void setAttributes lands without awaiting (nextjs-webpack · local-dev / local / node / canary)

🛠 Infra Events (absorbed by the harness)

Platform anomalies the e2e harness detected and worked around (e.g. a run the queue never picked up, replaced by a fresh run). Clustered timestamps indicate a backend blip; a steady drip indicates a platform issue worth escalating.

  • run-pickup-stall · runs app-generated source against a registered step (tanstack-start) · at 00:30:30Z · abandoned wrun_01M4VX290204CE9CF7Q6BJ2A12
  • cold-start-warmup · suite warmup (tanstack-start) · at 00:30:31Z · abandoned wrun_01M4VX2906KBZSAFP21XJRBPSH
  • run-pickup-stall · abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works (nextjs-webpack) · at 00:40:51Z · abandoned wrun_01M4VXN7FGZPNS0J8AP8Y4C205
  • run-pickup-stall · abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay (nextjs-webpack) · at 00:40:51Z · abandoned wrun_01M4VXN7G2W4NJCBVDVR11DMSQ

E2E Test Summary

Summary
Passed Failed Skipped Total
✅ ▲ Vercel Production 3982 0 878 4860
✅ 💻 Local Development 4669 0 551 5220
✅ 📦 Local Production 4669 0 551 5220
✅ 🐘 Local Postgres 4669 0 551 5220
✅ 🪟 Windows 348 0 12 360
✅ 🌐 Cross-language Conformance 68 0 87 155
✅ dynamic-runs 0 0 0 0
✅ vercel-http-transport 897 0 183 1080
✅ vercel-multi-region 27 0 0 27
✅ vercel-ws-transport 607 0 113 720
Total 19936 0 2926 22862
Details by Category

✅ ▲ Vercel Production

App Passed Failed Skipped
✅ astro-node 145 0 35
✅ astro-quickjs 145 0 35
✅ example-node 145 0 35
✅ example-quickjs 145 0 35
✅ express-node 145 0 35
✅ express-quickjs 145 0 35
✅ fastify-node 145 0 35
✅ fastify-quickjs 145 0 35
✅ hono-node 145 0 35
✅ hono-quickjs 145 0 35
✅ nest-node 145 0 35
✅ nest-quickjs 145 0 35
✅ nextjs-turbopack-node 172 0 8
✅ nextjs-turbopack-quickjs 172 0 8
✅ nextjs-webpack-node 172 0 8
✅ nextjs-webpack-quickjs 172 0 8
✅ nitro-node 145 0 35
✅ nitro-quickjs 145 0 35
✅ nuxt-node 145 0 35
✅ nuxt-quickjs 145 0 35
✅ python-node 66 0 114
✅ sveltekit-node 164 0 16
✅ sveltekit-quickjs 164 0 16
✅ tanstack-start-node 145 0 35
✅ tanstack-start-quickjs 145 0 35
✅ vite-node 145 0 35
✅ vite-quickjs 145 0 35

✅ 💻 Local Development

App Passed Failed Skipped
✅ astro-stable-node 151 0 29
✅ astro-stable-quickjs 151 0 29
✅ express-stable-node 151 0 29
✅ express-stable-quickjs 151 0 29
✅ fastify-stable-node 151 0 29
✅ fastify-stable-quickjs 151 0 29
✅ hono-stable-node 151 0 29
✅ hono-stable-quickjs 151 0 29
✅ nest-stable-node 151 0 29
✅ nest-stable-quickjs 151 0 29
✅ nextjs-turbopack-canary-node 179 0 1
✅ nextjs-turbopack-canary-quickjs 179 0 1
✅ nextjs-turbopack-quickjs-snapshot 179 0 1
✅ nextjs-turbopack-stable-node 179 0 1
✅ nextjs-turbopack-stable-quickjs 179 0 1
✅ nextjs-webpack-canary-node 179 0 1
✅ nextjs-webpack-canary-quickjs 179 0 1
✅ nextjs-webpack-stable-node 179 0 1
✅ nextjs-webpack-stable-quickjs 179 0 1
✅ nitro-stable-node 151 0 29
✅ nitro-stable-quickjs 151 0 29
✅ nuxt-stable-node 151 0 29
✅ nuxt-stable-quickjs 151 0 29
✅ sveltekit-stable-node 170 0 10
✅ sveltekit-stable-quickjs 170 0 10
✅ tanstack-start-node 151 0 29
✅ tanstack-start-quickjs 151 0 29
✅ vite-stable-node 151 0 29
✅ vite-stable-quickjs 151 0 29

✅ 📦 Local Production

App Passed Failed Skipped
✅ astro-stable-node 151 0 29
✅ astro-stable-quickjs 151 0 29
✅ express-stable-node 151 0 29
✅ express-stable-quickjs 151 0 29
✅ fastify-stable-node 151 0 29
✅ fastify-stable-quickjs 151 0 29
✅ hono-stable-node 151 0 29
✅ hono-stable-quickjs 151 0 29
✅ nest-stable-node 151 0 29
✅ nest-stable-quickjs 151 0 29
✅ nextjs-turbopack-canary-node 179 0 1
✅ nextjs-turbopack-canary-quickjs 179 0 1
✅ nextjs-turbopack-quickjs-snapshot 179 0 1
✅ nextjs-turbopack-stable-node 179 0 1
✅ nextjs-turbopack-stable-quickjs 179 0 1
✅ nextjs-webpack-canary-node 179 0 1
✅ nextjs-webpack-canary-quickjs 179 0 1
✅ nextjs-webpack-stable-node 179 0 1
✅ nextjs-webpack-stable-quickjs 179 0 1
✅ nitro-stable-node 151 0 29
✅ nitro-stable-quickjs 151 0 29
✅ nuxt-stable-node 151 0 29
✅ nuxt-stable-quickjs 151 0 29
✅ sveltekit-stable-node 170 0 10
✅ sveltekit-stable-quickjs 170 0 10
✅ tanstack-start-node 151 0 29
✅ tanstack-start-quickjs 151 0 29
✅ vite-stable-node 151 0 29
✅ vite-stable-quickjs 151 0 29

✅ 🐘 Local Postgres

App Passed Failed Skipped
✅ astro-stable-node 151 0 29
✅ astro-stable-quickjs 151 0 29
✅ express-stable-node 151 0 29
✅ express-stable-quickjs 151 0 29
✅ fastify-stable-node 151 0 29
✅ fastify-stable-quickjs 151 0 29
✅ hono-stable-node 151 0 29
✅ hono-stable-quickjs 151 0 29
✅ nest-stable-node 151 0 29
✅ nest-stable-quickjs 151 0 29
✅ nextjs-turbopack-canary-node 179 0 1
✅ nextjs-turbopack-canary-quickjs 179 0 1
✅ nextjs-turbopack-quickjs-snapshot 179 0 1
✅ nextjs-turbopack-stable-node 179 0 1
✅ nextjs-turbopack-stable-quickjs 179 0 1
✅ nextjs-webpack-canary-node 179 0 1
✅ nextjs-webpack-canary-quickjs 179 0 1
✅ nextjs-webpack-stable-node 179 0 1
✅ nextjs-webpack-stable-quickjs 179 0 1
✅ nitro-stable-node 151 0 29
✅ nitro-stable-quickjs 151 0 29
✅ nuxt-stable-node 151 0 29
✅ nuxt-stable-quickjs 151 0 29
✅ sveltekit-stable-node 170 0 10
✅ sveltekit-stable-quickjs 170 0 10
✅ tanstack-start-node 151 0 29
✅ tanstack-start-quickjs 151 0 29
✅ vite-stable-node 151 0 29
✅ vite-stable-quickjs 151 0 29

✅ 🪟 Windows

App Passed Failed Skipped
✅ nextjs-turbopack-node 174 0 6
✅ nextjs-turbopack-quickjs 174 0 6

✅ 🌐 Cross-language Conformance

App Passed Failed Skipped
✅ python 68 0 87

✅ dynamic-runs

App Passed Failed Skipped
✅ astro-vercel 0 0 0
✅ example-vercel 0 0 0
✅ express-vercel 0 0 0
✅ fastify-vercel 0 0 0
✅ hono-vercel 0 0 0
✅ nest-vercel 0 0 0
✅ nextjs-turbopack-vercel 0 0 0
✅ nextjs-webpack-vercel 0 0 0
✅ nitro-vercel 0 0 0
✅ nuxt-vercel 0 0 0
✅ sveltekit-vercel 0 0 0
✅ tanstack-start-vercel 0 0 0
✅ vite-vercel 0 0 0

✅ vercel-http-transport

App Passed Failed Skipped
✅ example 145 0 35
✅ express 145 0 35
✅ hono 145 0 35
✅ nextjs-turbopack 172 0 8
✅ nitro 145 0 35
✅ vite 145 0 35

✅ vercel-multi-region

App Passed Failed Skipped
✅ nextjs-turbopack 27 0 0

✅ vercel-ws-transport

App Passed Failed Skipped
✅ example 145 0 35
✅ express 145 0 35
✅ nextjs-turbopack 172 0 8
✅ vite 145 0 35

📋 View full workflow run

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📊 Workflow Benchmarks

commit d8bd20c · Wed, 14 Oct 2026 00:40:11 GMT · run logs

Backend: vercel · app: nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 304 (-74%) 💚 1903 🔴 (+21%) 🔻 1979 🔴 (+20%) 🔻 2261 🔴 (+34%) 🔻 30
TTFS stream 280 (-81%) 💚 1902 🔴 (+24%) 🔻 1926 🔴 (+21%) 🔻 2007 🔴 (+12%) 30
TTFS hook + stream 2142 (+57%) 🔻 2295 🔴 (+21%) 🔻 2423 🔴 (+23%) 🔻 4388 🔴 (+105%) 🔻 30
Fan-out TTFS Promise.all(100 steps) 575 (-2.0%) 785 (+1.0%) 799 (+2.3%) 2416 (+26%) 🔻 10
Fan-out TTLS Promise.all(100 steps) 2904 (+43%) 🔻 4101 (+59%) 🔻 4139 (-8.6%) 7262 (+1.0%) 10
STSO 1020 steps (inline) 87 (-16%) 💚 114 (-14%) 130 (-14%) 222 (+16%) 🔻 1019
WO 1020 steps 115839 (-14%) 115839 (-14%) 115839 (-14%) 115839 (-14%) 1
📈 STSO distribution vs main (inline / queue-hop histograms)

1020 steps (inline)

Cumulative STSO time: main 133096ms → this run 115460ms (Δ -17636ms, -13%)

 50-100 ms  ░┃                        main   0  this  80   +80
100-150 ms  ██████████████████████┃█  main 913  this 887   -26
150-200 ms  ┃██                       main  99  this  36   -63
200-250 ms  ┃                         main   3  this  11    +8
250-300 ms  ┃                         main   2  this   3    +1
300-350 ms  ┃                         main   1  this   2    +1
500-550 ms  ┃                         main   1  this   0    -1
📜 Previous results (4)

2a23e1a

Fri, 09 Oct 2026 23:24:49 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 1570 (+432%) 🔻 1901 🔴 (+28%) 🔻 1936 🔴 (+26%) 🔻 1961 🔴 (+12%) 30
TTFS stream 1799 (+536%) 🔻 1902 🔴 (+33%) 🔻 1948 🔴 (+30%) 🔻 2094 🔴 (+27%) 🔻 30
TTFS hook + stream 1805 (+255%) 🔻 2231 🔴 (+30%) 🔻 2276 🔴 (+30%) 🔻 2429 🔴 (+35%) 🔻 30
Fan-out TTFS Promise.all(100 steps) 497 (-4.4%) 757 (+7.4%) 845 (+14%) 2273 (+30%) 🔻 10
Fan-out TTLS Promise.all(100 steps) 1068 (-73%) 💚 4262 (+3.3%) 4320 (+4.5%) 7459 (+69%) 🔻 10
STSO 1020 steps (inline) 64 (-26%) 💚 95 (-16%) 💚 115 (-14%) 150 (-32%) 💚 1019
WO 1020 steps 96010 (-15%) 💚 96010 (-15%) 💚 96010 (-15%) 💚 96010 (-15%) 💚 1

af4207f

Tue, 06 Oct 2026 20:51:44 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 2241 (+207%) 🔻 2441 🔴 (+124%) 🔻 2599 🔴 (+133%) 🔻 2680 🔴 (+123%) 🔻 30
TTFS stream 388 (+76%) 🔻 2321 🔴 (+121%) 🔻 2371 🔴 (+116%) 🔻 2454 🔴 (+72%) 🔻 30
TTFS hook + stream 2120 (+142%) 🔻 2621 🔴 (+98%) 🔻 2645 🔴 (+88%) 🔻 2853 🔴 (+83%) 🔻 30
Fan-out TTFS Promise.all(100 steps) 629 (-28%) 💚 820 (-52%) 💚 1028 (-42%) 💚 2711 (+45%) 🔻 10
Fan-out TTLS Promise.all(100 steps) 2578 (+12%) 3242 (-11%) 3288 (-13%) 8466 (+17%) 🔻 10
STSO 1020 steps (inline) 110 (+10%) 141 (+8.5%) 159 (+3.2%) 228 (+12%) 1019
WO 1020 steps 139848 (+6.2%) 139848 (+6.2%) 139848 (+6.2%) 139848 (+6.2%) 1

60588df

Fri, 25 Sep 2026 19:30:08 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 2079 (+12%) 2296 🔴 (+17%) 🔻 2316 🔴 (+16%) 🔻 2422 🔴 (+14%) 30
TTFS stream 2075 (+14%) 2281 🔴 (+18%) 🔻 2319 🔴 (+18%) 🔻 2390 🔴 (-3.0%) 30
TTFS hook + stream 637 (-69%) 💚 2617 🔴 (+19%) 🔻 2691 🔴 (+20%) 🔻 2968 🔴 (+21%) 🔻 30
Fan-out TTFS Promise.all(100 steps) 650 (+12%) 865 (+1.5%) 866 (-4.5%) 2652 (-23%) 💚 10
Fan-out TTLS Promise.all(100 steps) 2915 (+90%) 🔻 8797 (+207%) 🔻 9002 (+207%) 🔻 9765 (-30%) 💚 10
STSO 1020 steps (inline) 137 (+8.7%) 157 (-3.1%) 172 (-13%) 326 (-73%) 💚 1019
WO 1020 steps 162458 (-19%) 💚 162458 (-19%) 💚 162458 (-19%) 💚 162458 (-19%) 💚 1

fed6c9f

Wed, 23 Sep 2026 21:35:26 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 236 (-75%) 💚 2329 🔴 (+78%) 🔻 2643 🔴 (+96%) 🔻 2704 🔴 (+81%) 🔻 30
TTFS stream 252 (+47%) 🔻 2242 🔴 (+30%) 🔻 2613 🔴 (+50%) 🔻 2691 🔴 (+43%) 🔻 30
TTFS hook + stream 798 (+77%) 🔻 2621 🔴 (+25%) 🔻 2970 🔴 (+36%) 🔻 6687 🔴 (+178%) 🔻 30
Fan-out TTFS Promise.all(100 steps) 527 (+5.6%) 2673 (+282%) 🔻 2752 (+291%) 🔻 2783 (+50%) 🔻 10
Fan-out TTLS Promise.all(100 steps) 3102 (+97%) 🔻 5786 (+26%) 🔻 5851 (-19%) 💚 10177 (-43%) 💚 10
STSO 1020 steps (inline) 130 (+21%) 🔻 157 (+1.9%) 177 (+1.1%) 276 (-25%) 💚 1019
WO 1020 steps 158435 (+3.4%) 158435 (+3.4%) 158435 (+3.4%) 158435 (+3.4%) 1
ℹ️ Metric definitions & methodology

The collapsed STSO distribution section above buckets every step gap, split inline (same warm process — pure framework overhead) vs queue-hop (fresh process — dispatch, reinit, replay). █ = main, ┃ = this run, ░ = fill.

Best/P75/P90/P99 deltas compare against the most recent benchmark run on main at the time of this run. 🔻 flags a delta worse than +15%, 💚 one better than −15%.

Metrics — TTFS: time to first step body (in-deployment start() → first step body) · Fan-out TTFS: fan-out time to first step (in-deployment start() → first of the parallel step bodies to complete) · Fan-out TTLS: fan-out time to last step (in-deployment start() → last of the parallel step bodies to complete, i.e. when the Promise.all resolves) · STSO: step-to-step overhead (gap between consecutive step bodies) · WO: workflow overhead (whole-run time outside step bodies, in-deployment anchored)

Scenarios — step: one trivial no-op step, no stream; no hooks, so the run stays in turbo mode (in-process fast path) · stream: one streaming step; no hooks, so the run stays in turbo mode (in-process fast path) · hook + stream: registers a hook before one step, which exits turbo mode (dispatch path) · 1020 steps: 1020 trivial sequential steps; STSO is measured between consecutive steps in the given step ranges, and WO is the whole-run overhead outside step bodies · Promise.all(100 steps): 100 trivial no-op steps started together in a single Promise.all; Fan-out TTFS is the first of them to complete and Fan-out TTLS the last, both from the in-deployment clientStart, so their gap is the spread the runtime adds across the fan-out

🔴 marks a percentile over its target (within target is left unmarked). Targets (p75/p90/p99, ms) — TTFS 200/300/600

All timestamps are deployment-side; runs are triggered in-deployment, so the CI runner and api.vercel.com sit outside every measured window. TTFS = start() → first step body (includes dispatch + any cold start); Fan-out TTFS/TTLS = first/last step completion of one Promise.all from the same anchor (the gap is the runtime’s fan-out spread); STSO/WO between step bodies. Streaming delivery performance is measured in durabench.

Cold starts stay in the numbers (real bursty-workload latency, inflates P75+); Best is the warm floor.

@socket-security

socket-security Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​nanoid@​5.1.6 ⏵ 5.1.16100100 +2279 -194100

View full report

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Sim World

Simulated world deterministic testing for races. Traces

🟢 world-sim scenario book — 0 fail of 42 total

fence=per-spec

scenario outcome events virt replay violations
✅ smoke-no-steps completed 3 0ms ok 0
✅ smoke-one-step completed 6 0ms ok 0
✅ hook-at-step-started completed 12 0ms ok 0
✅ hook-at-step-completed completed 12 0ms ok 0
✅ hook-at-hook-created completed 12 0ms ok 0
✅ deadline-hook-wins completed 7 1.0h ok 0
✅ deadline-expires completed 7 1.0h ok 0
✅ step-vs-timer-early-settlement completed 8 1.0h ok 0
✅ long-sleep completed 11 30.0d ok 0
✅ hook-never-arrives stalled 3 0ms skipped 0
✅ step-retries-twice completed 10 2.0s ok 0
✅ parallel-steps completed 9 0ms ok 0
✅ hook-on-execution-state completed 12 0ms ok 0
✅ peek-hook-before-branch completed 12 0ms ok 0
✅ peek-hook-after-branch completed 12 0ms ok 0
✅ peek-hook-at-registration completed 12 0ms ok 0
✅ race-hook-before-probe completed 12 0ms ok 0
✅ race-hook-after-probe completed 12 0ms ok 0
✅ race-duplicate-delivery completed 13 0ms ok 0
✅ attr-hook-before-step completed 11 0ms ok 0
✅ attr-hook-after-step completed 11 0ms ok 0
✅ attr-from-step-body completed 13 0ms ok 0
✅ fork-hook-after-timeout completed 14 1.0m ok 0
✅ fork-hook-before-timeout completed 14 1.0m ok 0
✅ count-hook-after-timeout completed 17 1.0m ok 0
✅ count-hook-before-timeout completed 20 1.0m ok 0
✅ stale-read-step-count-fork completed 20 1.0m ok 0
✅ stale-read-equal-step-counts completed 14 1.0m ok 0
✅ step-vs-step-fork completed 12 0ms ok 0
✅ step-vs-step-fork-fenced completed 12 0ms ok 0
✅ fence-catches-benign-direction completed 12 5ms ok 0
✅ in-flight-before-decision completed 17 1.0m ok 0
✅ in-flight-before-decision-counted completed 17 1.0m ok 0
✅ in-flight-after-decision completed 19 2.0m ok 0
✅ stale-read-step-count-fork-fenced completed 20 1.0m ok 0
✅ fork-hook-wins completed 13 1.0m ok 0
✅ fork-timeout-wins completed 13 1.0m ok 0
✅ unclaimed-payload-under-fork completed 17 1.0m ok 0
✅ claimed-payload-under-fork completed 17 1.0m ok 0
✅ writers-independent-step-bodies completed 12 0ms ok 0
✅ writers-scripted-tempo completed 12 0ms ok 0
✅ cancel-mid-step cancelled 7 0ms skipped 0

Full trace: world-sim.txt

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor
Framework Flow route Step reg. Framework output
hono 267.4 KiB (±0) 95.6 KiB (±0) 1.99 MiB (-66 B)
nextjs-turbopack 274.8 KiB (±0) 426 B (±0) 972.2 KiB (-119 B)
About these numbers

Sizes are gzip; parentheses show the change against main.
Flow route and Step reg. gate this job, on raw bytes rather than the gzip shown, at max(2%, 50.0 KiB). Framework output is informational.

d8bd20c · run

pranaygp added a commit that referenced this pull request Sep 23, 2026
Same change as #4335 on main. Refs #3842.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
pranaygp added a commit that referenced this pull request Sep 23, 2026
Same change as on main (#4335). The plain bump to nanoid 5.1.16 broke the
hook-sleep-interaction replay fixtures, because nanoid 5.1.16 draws a
different number of random bytes per id.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
@workflow/core pinned nanoid 5.1.6, which is affected by
GHSA-28wg-ghj8-5hjv. Bumping to 5.1.16 is not replay-safe: its
customRandom draws 21 bytes per id instead of 34, which changes default
hook tokens and every seeded value drawn after them for the same run.
Inline nanoid 5.1.6's customRandom(urlAlphabet, 21) with a golden test and
remove the dependency.

Closes #3842.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main (54b48ef4d) as a single commit and marked ready.

CI notes: the red Vercel Prod / HTTP / WS e2e lanes all fail on one test, createHook({ experimental_force: true }) > declines to take a token from a run whose runtime predates involuntary disposal (90s timeout). It was added in #4193 and fails the same way on unrelated PRs like #4428. The one Local Dev failure (astro - stable node, a run can take over its own earlier hook) is a timeout in a test that uses an explicit token, so it never reaches the nanoid generator; it passes on every other lane. Unit tests, lint, typecheck and all Local Prod/Postgres lanes pass.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@VaguelySerious

Copy link
Copy Markdown
Member

This PR looks fine, thought we're also not affected by the issue (no attacker-passed values for ID generation), ignoring for now

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>

pranaygp commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged latest main (af4207f81). No conflicts, and no new direct nanoid imports on main. @workflow/core test (3070) and typecheck pass locally.

CI on this push:

  • E2E Vercel HTTP Transport (nextjs-turbopack) / E2E Required Check: the pages-router tests failed with Failed to mint GitHub Actions OIDC token: 503 Service Unavailable in scripts/trusted-sources-headers.mjs. That's a CI infrastructure error, not this change.
  • Vitest Plugin Tests (quickjs): hook-token-reuse > same run can recreate a hook with the same token after dispose() failed once. It uses an explicit token, not the seeded generator. It passes 5/5 locally under WORKFLOW_VM=quickjs on this branch.
  • Vercel – workflow-web: a preview deployment failure, unrelated.

These need a rerun of the failed jobs, which I can't trigger from here.

🤖 Generated with Claude Code

# Conflicts:
#	workbench/nextjs-turbopack/package.json
#	workbench/nextjs-webpack/package.json

@VaguelySerious VaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI review: no blocking issues

"@workflow/core": patch
---

Security: remove the `nanoid` dependency (pinned at 5.1.6, affected by [GHSA-28wg-ghj8-5hjv](https://github.com/advisories/GHSA-28wg-ghj8-5hjv)). Default hook tokens now come from a built-in copy of the same generator, so tokens and seeded random values stay identical for runs recorded on earlier versions. Upgrading `nanoid` itself would have changed them, because `nanoid@5.1.16` draws a different number of random bytes per id.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI Review: Nit

The changeset is used verbatim in the changelog, and the repo convention is one terse line with no implementation detail. Something like: Security: remove the nanoid dependency (GHSA-28wg-ghj8-5hjv). Hook tokens are unchanged for existing runs. The rationale for not bumping fits better in the PR description, where it already is.

const BYTES_PER_ID = 34;

export function createSeededNanoid(random: () => number): () => string {
return () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI Review: Note

Checked this against the real nanoid@5.1.6 locally: 5,000 random seeds, 5 tokens each, with 0-3 extra PRNG draws between tokens to mimic Math.random() calls in workflow code. All 25,000 tokens matched and the PRNG ended at the same position every time. The returned function also takes no size argument, which is fine: all callers (hook.ts and both QuickJS __generateNanoid bindings) call it with no arguments.

@github-actions github-actions Bot mentioned this pull request Oct 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #4881. Merge conflicts were resolved by AI — please review carefully. (backport job run)

This branch was successfully deployed

18 active (17 outdated) deployments
Preview – workflow-docs — d8bd20cb Deployed Oct 14, 2026 by vercel[bot]
Preview – workbench-sveltekit-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-express-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-tanstack-start-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-vite-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workflow-tarballs — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – example-nextjs-workflow-turbopack — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-astro-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-nuxt-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-hono-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-fastify-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-nestjs-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – example-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-nitro-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workflow-web — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workbench-python-workflow — 60588df9 Deployed Sep 25, 2026 by vercel[bot]
Preview – workflow-swc-playground — fed6c9fe Deployed Sep 23, 2026 by vercel[bot]
Preview – example-nextjs-workflow-webpack — fed6c9fe Deployed Sep 23, 2026 by vercel[bot]
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.

Hardcoded dep version make it hard to patch vulnerabilities

3 participants