From 714c7bdcea6ab8d0b7b0e2093ddb4d95e2015da0 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Sun, 1 Feb 2026 19:23:28 +0000 Subject: [PATCH] fix(audit): exclude workspace devDependencies in --prod mode (#26675) When running `bun audit --prod` from a monorepo root, devDependencies of workspace packages were incorrectly being included in the audit. The bug was in the BFS traversal of buildProductionPackageSet(), which didn't check isDev() for transitive dependencies. This fix adds the missing isDev() check so workspace package devDependencies are properly excluded when auditing production deps. Co-Authored-By: Claude Opus 4.5 --- src/cli/audit_command.zig | 4 +- test/regression/issue/26675.test.ts | 171 ++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 test/regression/issue/26675.test.ts diff --git a/src/cli/audit_command.zig b/src/cli/audit_command.zig index 8a7eb1bd97..89804b5bce 100644 --- a/src/cli/audit_command.zig +++ b/src/cli/audit_command.zig @@ -220,7 +220,9 @@ fn buildProductionPackageSet(allocator: std.mem.Allocator, pm: *PackageManager, const current_dep_slice = current_deps.get(dependencies); const current_res_slice = current_resolutions.get(resolutions); - for (current_dep_slice, current_res_slice) |_, resolved_pkg_id| { + for (current_dep_slice, current_res_slice) |dep, resolved_pkg_id| { + // Skip devDependencies - they should not be included in production audit + if (dep.behavior.isDev()) continue; if (resolved_pkg_id >= pkg_names.len) continue; const pkg_name = pkg_names[resolved_pkg_id].slice(buf); diff --git a/test/regression/issue/26675.test.ts b/test/regression/issue/26675.test.ts new file mode 100644 index 0000000000..6ca83d5bc9 --- /dev/null +++ b/test/regression/issue/26675.test.ts @@ -0,0 +1,171 @@ +import { spawn } from "bun"; +import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import { bunEnv, bunExe, gunzipJsonRequest, tempDir } from "harness"; + +// Test for GitHub issue #26675: +// `bun audit --prod` should not include devDependencies of workspace packages + +let server: Bun.Server; + +beforeAll(() => { + server = Bun.serve({ + port: 0, + fetch: async req => { + const body = await gunzipJsonRequest(req); + + // Return vulnerabilities for ms@0.7.0, empty for everything else + if (body && body.ms && body.ms.includes("0.7.0")) { + return Response.json({ + ms: [ + { + id: 1094419, + url: "https://github.com/advisories/GHSA-w9mr-4mfr-499f", + title: "Vercel ms Inefficient Regular Expression Complexity vulnerability", + severity: "moderate", + vulnerable_versions: "<2.0.0", + }, + ], + }); + } + + return Response.json({}); + }, + }); +}); + +afterAll(() => { + server.stop(); +}); + +const fakeIntegrity = "sha512-V8E0l1jyyeSSS9R+J9oljx5eq2rqzClInuwaPcyuv0Mm3ViI/3/rcc4rCEO8i4eQ4I0O0FAGYDA2i5xWHHPhzg=="; + +describe("issue #26675 - bun audit --prod with workspace devDependencies", () => { + test("--prod flag should exclude devDependencies of workspace packages", async () => { + using dir = tempDir("bun-test-audit-workspace-prod", { + "package.json": JSON.stringify({ + name: "test-monorepo", + private: true, + workspaces: ["packages/*"], + }), + "packages/frontend/package.json": JSON.stringify({ + name: "test-frontend", + devDependencies: { + ms: "0.7.0", + }, + }), + "bun.lock": JSON.stringify({ + lockfileVersion: 1, + workspaces: { + "": { + name: "test-monorepo", + }, + "packages/frontend": { + name: "test-frontend", + devDependencies: { + ms: "0.7.0", + }, + }, + }, + packages: { + "test-frontend": ["test-frontend@workspace:packages/frontend"], + ms: ["ms@0.7.0", "", {}, fakeIntegrity], + }, + }), + }); + + const url = server.url.toString().slice(0, -1); + + // First, verify that without --prod, the vulnerability is reported + { + await using proc = spawn({ + cmd: [bunExe(), "audit"], + stdout: "pipe", + stderr: "pipe", + cwd: String(dir), + env: { + ...bunEnv, + NPM_CONFIG_REGISTRY: url, + }, + }); + + const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]); + + expect(stdout).toContain("ms"); + expect(stdout).toContain("vulnerabilities"); + expect(exitCode).toBe(1); + } + + // Now verify that with --prod, the devDependency vulnerability is NOT reported + { + await using proc = spawn({ + cmd: [bunExe(), "audit", "--prod"], + stdout: "pipe", + stderr: "pipe", + cwd: String(dir), + env: { + ...bunEnv, + NPM_CONFIG_REGISTRY: url, + }, + }); + + const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]); + + expect(stdout).toContain("No vulnerabilities found"); + expect(exitCode).toBe(0); + } + }); + + test("--prod flag should still report production dependencies of workspace packages", async () => { + using dir = tempDir("bun-test-audit-workspace-prod-deps", { + "package.json": JSON.stringify({ + name: "test-monorepo", + private: true, + workspaces: ["packages/*"], + }), + "packages/frontend/package.json": JSON.stringify({ + name: "test-frontend", + dependencies: { + ms: "0.7.0", + }, + }), + "bun.lock": JSON.stringify({ + lockfileVersion: 1, + workspaces: { + "": { + name: "test-monorepo", + }, + "packages/frontend": { + name: "test-frontend", + dependencies: { + ms: "0.7.0", + }, + }, + }, + packages: { + "test-frontend": ["test-frontend@workspace:packages/frontend"], + ms: ["ms@0.7.0", "", {}, fakeIntegrity], + }, + }), + }); + + const url = server.url.toString().slice(0, -1); + + // With --prod, production dependency vulnerabilities should still be reported + await using proc = spawn({ + cmd: [bunExe(), "audit", "--prod"], + stdout: "pipe", + stderr: "pipe", + cwd: String(dir), + env: { + ...bunEnv, + NPM_CONFIG_REGISTRY: url, + }, + }); + + const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]); + + expect(stdout).toContain("ms"); + expect(stdout).toContain("vulnerabilities"); + expect(exitCode).toBe(1); + }); +});