Skip to content

[Security] bun.lock currently pins fastify 5.10.0 with advisory-carrying transitives (find-my-way 9.6.0, fast-uri 3.1.0/4.1.0) inside the runtime closure, and no workflow queries an advisory database #779

Description

@pathosDev

Component: bun.lock
Severity (assessment): INFORMATIONAL
CWE: CWE-1104 (Use of Unmaintained/Vulnerable Third Party Components)
Related: #539

fastify is one of only two hard runtime dependencies (package.json:238-241). The lockfile resolves it to 5.10.0, whose transitive router (find-my-way@9.6.0) and URI parser (fast-uri@3.1.0 / 4.1.0) are all at versions with published HIGH advisories. Nothing in the ten workflows queries an advisory database, so the lockfile can sit on known-vulnerable versions indefinitely with every gate green.

Exploit walkthrough

Preconditions vary by advisory and by how the consumer resolves. Most direct: find-my-way is the router behind FastifyBackend, which is the framework's default HTTP backend. GHSA-c96f-x56v-gq3h is remotely triggerable by any client that can open an HTTP/2 connection to an actor-ts HTTP server — no authentication needed — and degrades the router into a CPU-bound state. fast-uri's host-confusion advisories matter wherever a parsed authority is used for a trust decision (origin checks, redirect validation, schema $ref resolution inside ajv, which fastify uses for request-body validation).
Honest scoping of who is actually exposed: consumers installing actor-ts from npm do NOT receive bun.lock — they resolve fastify: ^5.10.0 fresh and today would get 5.11.0 with patched transitives. The parties genuinely running the vulnerable versions are (a) this repository's own CI, including the prepublishOnly test run inside the credential-bearing publish job, (b) every Docker integration runner (tests/integration/**/Dockerfile.runner, all of which RUN bun install), (c) any consumer with a pinned or mirrored resolution, and (d) anyone who clones and runs the framework. The finding is therefore about the absence of a detection mechanism as much as the specific versions.

Evidence — bun.lock

Queried the npm advisory bulk endpoint (https://registry.npmjs.org/-/npm/v1/security/advisories/bulk, read-only POST) with the 294 distinct name@version pairs parsed out of bun.lock. Results inside the RUNTIME closure — computed by walking bun.lock from dependencies = {fastify, ts-pattern} only (50 packages):

HIGH      find-my-way@9.6.0   vulnerable <=9.6.0   DDoS with HTTP2                                        GHSA-c96f-x56v-gq3h
HIGH      fast-uri@3.1.0      vulnerable <=3.1.0   path traversal via percent-encoded dot segments        GHSA-q3j6-qgpj-74h6
HIGH      fast-uri@3.1.0      vulnerable <=3.1.1   host confusion via percent-encoded authority delims    GHSA-v39h-62p7-jpjc
HIGH      fast-uri@3.1.0      vulnerable >=3.0.0 <3.1.3   host confusion via failed IDN canonicalization  GHSA-4c8g-83qw-93j6
HIGH      fast-uri@3.1.0/4.1.0 vulnerable <=3.1.3 / >=4.0.0 <=4.1.0  host confusion via literal backslash  GHSA-v2hh-gcrm-f6hx

Dev-tree only (not shipped to consumers, but present in every CI run and every prepublishOnly test run):

HIGH      @fastify/static@10.1.0   route guard bypass via path traversal      GHSA-83w8-p2f5-377r
MODERATE  @fastify/static@10.1.0   authz bypass via non-canonical URL paths   GHSA-8pvw-jcv7-9cmj
HIGH      ws@8.20.0                memory exhaustion DoS from tiny fragments  GHSA-96hv-2xvq-fx4p
MODERATE  ws@8.20.0                uninitialized memory disclosure            GHSA-58qx-3vcg-4xpx
HIGH/MOD  brace-expansion@5.0.5    3 DoS advisories                           GHSA-mh99-…, -3jxr-…, -jxxr-…
MODERATE  @hono/node-server@2.0.9  unauth. memory-leak DoS via aborted WS handshake  GHSA-9mqv-5hh9-4cgg
MODERATE  qs@6.15.1 / LOW body-parser@2.2.2

Fixed versions all exist today: fastify 5.11.0, find-my-way 9.7.0, fast-uri 4.1.2, ws 8.21.1, @fastify/static 10.1.2, @hono/node-server 2.0.12 (queried live from the registry).
No scan step exists anywhere — grepping .github/ for audit|snyk|osv|codeql|scorecard|trivy|dependency-review returns only prose in ISSUE_TEMPLATE/security_report.yml and a comment in integration-brokers.yml.
Note on @fastify/static: it is a devDependency and NOT a peerDependency (package.json:117), and src/http/static/StaticFiles.ts:3 documents that the framework deliberately does not use it — so those two advisories are dev-surface only.

Why the existing guard does not cover it

Dependabot runs daily against / (dependabot.yml:6-12) with minor and patch grouped, so fastify bumps do get PR'd. But Dependabot version updates operate on package.json ranges, and ^5.10.0 already admits 5.11.0 — and per the project's own documented experience (docs-checks.yml:41-46: "Dependabot bumps docs/package.json but never regenerates docs/bun.lock"), the Bun lockfile is not maintained by that flow at all. The lockfile-sync job (docs-checks.yml:47-60) catches lockfile/manifest DRIFT, which is a different property from lockfile FRESHNESS against advisories: a lockfile can be perfectly in sync with its manifest and still pin four HIGH-severity transitive versions, which is exactly the current state. Nothing anywhere queries an advisory database.

Suggested fix

Refresh the lockfile (bun update fastify / bun install to pull find-my-way ≥9.7.0 and fast-uri ≥4.1.2, plus ws ≥8.21.1, @fastify/static ≥10.1.2, @hono/node-server ≥2.0.12 in the dev tree). Then add a scanning gate: a bun audit --audit-level=high step in package-health.yml (which already owns "shape of what gets published" checks), and enable GitHub's Dependabot security updates plus actions/dependency-review-action on pull requests so a PR that introduces an advisory-carrying version fails before merge rather than after release.

Relationship to existing issues

Adjacent to #539, but a distinct mechanism. I verified every version pin claimed: bun.lock:392 fastify@5.10.0, :406 find-my-way@9.6.0, :390 fast-uri@3.1.0 and :694 fast-json-stringify/fast-uri@4.1.0, :660 ws@8.20.0, :116 @fastify/static@10.1.0, :120 @hono/node-server@2.0.9, :308 brace-expansion@5.0.5 — and package.json confirms fastify is one of only two runtime dependencies. I also confirmed the negative claim: grepping .github/ for audit|snyk|osv|codeql|scorecard|trivy|dependency-review returns only prose in the issue template and one comment in integration-brokers.yml — no scanning step exists. I could not independently confirm the advisory IDs (no network), so the GHSA list is taken on the finder's evidence. Relative to the corpus: #539 is a FEATURE request for the tooling class ("no dependency vulnerability scanning (osv-scanner / dependency-review-action / audit step)") and shares the second half of this finding. What #539 does not record — and what is separately actionable today — is that the lockfile is currently sitting on advisory-carrying versions in the runtime closure and that fixed releases already exist. So: file it, cross-referencing #539, scoped to the lockfile refresh plus a bun audit --audit-level=high gate in package-health.yml. Severity MEDIUM->LOW on the finding's own honest scoping: npm consumers do not receive bun.lock and resolve ^5.10.0 fresh, so the shipped package is unaffected; the exposed parties are this repo's CI, the Docker runners, and clone-and-run developers, and the remediation is a bun install away.

Verification status

Found in the second, independent whole-framework security re-audit of 2026-08-02 (v0.12.0) — a fresh pass run without reference to the first wave's findings, then triaged against the existing tracker and adjudicated by verifiers instructed to refute it.

Verifier note

I verified every lockfile pin claimed: bun.lock:392 fastify@5.10.0, :406 find-my-way@9.6.0, :390 fast-uri@3.1.0, :694 fast-json-stringify/fast-uri@4.1.0, :660 ws@8.20.0, :116 @fastify/static@10.1.0, :120 @hono/node-server@2.0.9, :308 brace-expansion@5.0.5. package.json confirms dependencies is exactly {fastify, ts-pattern}. I confirmed the negative claim by grep: audit|snyk|osv|codeql|scorecard|trivy|dependency-review across .github/ matches only prose in ISSUE_TEMPLATE/security_report.yml and one comment in integration-brokers.yml — none of the ten workflows queries an advisory database. I also spot-checked two advisories live rather than taking them on faith: GHSA-c96f-x56v-gq3h (find-my-way ≤9.6.0, HIGH/7.5, patched 9.7.0) and GHSA-v2hh-gcrm-f6hx (fast-uri ≥3.0.0 ≤3.1.3 and ≥4.0.0 ≤4.1.0, HIGH/7.5, patched 3.1.4/4.1.1). Both apply to the pinned versions. The finder's own scoping of consumer exposure is correct and I confirmed the mechanism: package.json files is ["dist/","README.md","CHANGELOG.md","LICENSE"], so bun.lock is not published and npm consumers resolve ^5.10.0 fresh. Corrected severity LOW → INFORMATIONAL, for three reasons established above: the one advisory with a concrete remote-exploit story is unreachable because no code path in src/ creates an HTTP/2 server; the Docker exposure claim collapses to a single Dockerfile once you check that the broker runners install without a lockfile; and no reachable trust decision in this codebase consumes a fast-uri-parsed authority (it enters only via ajv/fast-json-stringify internals). What genuinely remains is that the root lockfile is stale against published advisories and that nothing detects it — and the second half is already filed as #539. File this scoped to the mechanical remediation (bun update to refresh the pins) plus the bun audit --audit-level=high gate, cross-referencing #539, and without the HTTP/2 exploit narrative.

Correction applied: Three factual corrections, all reducing scope. (1) The headline exploit is NOT reachable. GHSA-c96f-x56v-gq3h requires Node's HTTP/2 server (I fetched the advisory: "improper handling of HTTP/2 method values that can resolve inherited object properties"). grep -rniE 'http2|http/2|allowHTTP1|createSecureServer' src/ returns ZERO hits, and FastifyBackend's constructor (src/http/backend/FastifyBackend.ts:49-50) defaults to { logger: false } — the framework never enables HTTP/2 on any backend. The claim "remotely triggerable by any client that can open an HTTP/2 connection to an actor-ts HTTP server" must be struck; only a consumer who explicitly passes { http2: true } into new FastifyBackend(...) is exposed. Also, the advisory's impact is an application crash (prototype pollution → CWE-1321), not "degrades the router into a CPU-bound state". (2) Exposure item (b) is wrong: the sixteen broker runners do NOT use bun.lock. Each Dockerfile.runner copies only tests/integration/brokers/package.json and runs bun install with no lockfile (verified in tests/integration/brokers/s3/Dockerfile.runner:20-22; grep -rn 'bun.lock' tests/ --include=Dockerfile* matches only tests/integration/Dockerfile.node:39). Those images therefore resolve fresh and get patched versions. Only one of the seventeen integration Dockerfiles is affected. (3) fast-uri's patched versions are 3.1.4 / 4.1.1 per GHSA-v2hh-gcrm-f6hx, not 4.1.2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginfrastructureCI / build / live-integration testspriority: lowNice-to-have / niche / demand-drivensecuritySecurity-relevant — see severity label for impact tierseverity: lowMinor / informational / mitigated-by-design

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions