From ec863f0c75c01f3decd52d02a8bc3febc07b03f8 Mon Sep 17 00:00:00 2001 From: Martin Torp Date: Thu, 30 Apr 2026 15:28:29 +0200 Subject: [PATCH 1/4] feat(fix): add --package-managers flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forward Coana's new --package-managers filter (coana-tech/coana-package-manager#2214) through socket fix so users can narrow fix computation to specific package managers within an ecosystem (e.g. only PNPM in a monorepo that mixes pnpm/yarn/npm). The flag accepts comma- or space-separated values, is case-insensitive (normalized to uppercase before validation and forward), and is passed to both `find-vulnerabilities` and `compute-fixes-and-upgrade-purls`. When combined with --ecosystems, both filters must match (Coana intersects them per-artifact). Valid values mirror Coana's getFilterablePackageManagers(): CARGO, COMPOSER, GO, GRADLE, MAVEN, NPM, NUGET, PIPENV, PIP_REQUIREMENTS, PNPM, POETRY, RUBYGEMS, RUSH, SBT, YARN. Out of scope (matching the Coana PR): --package-managers is not added to socket scan reach / the coana run command — that command's --purl-types runs at ecosystem-level pre-install and a per-PM filter would require a larger refactor in Coana. --- src/commands/fix/cmd-fix.integration.test.mts | 93 +++++++++++++++++++ src/commands/fix/cmd-fix.mts | 32 +++++++ src/commands/fix/coana-fix.mts | 14 +++ src/commands/fix/handle-fix.mts | 3 + src/commands/fix/types.mts | 1 + src/utils/package-manager.mts | 38 ++++++++ 6 files changed, 181 insertions(+) create mode 100644 src/utils/package-manager.mts diff --git a/src/commands/fix/cmd-fix.integration.test.mts b/src/commands/fix/cmd-fix.integration.test.mts index 452332ffe..013b00d17 100644 --- a/src/commands/fix/cmd-fix.integration.test.mts +++ b/src/commands/fix/cmd-fix.integration.test.mts @@ -183,6 +183,7 @@ describe('socket fix', async () => { --no-apply-fixes Compute fixes only, do not apply them. Logs what upgrades would be applied. If combined with --output-file, the output file will contain the upgrades that would be applied. --no-major-updates Do not suggest or apply fixes that require major version updates of direct or transitive dependencies --output-file Path to store upgrades as a JSON file at this path. + --package-managers Limit fix analysis to specific package managers within an ecosystem (e.g. NPM, PNPM, YARN, MAVEN, POETRY). Accepts space- or comma-separated values and is case-insensitive. When combined with --ecosystems, an artifact must satisfy both filters. --pr-limit Maximum number of pull requests to create in CI mode (default 10). Has no effect in local mode. --range-style Define how dependency version ranges are updated in package.json (default 'preserve'). Available styles: @@ -1127,6 +1128,98 @@ describe('socket fix', async () => { ) }) + describe('--package-managers flag behavior', () => { + cmdit( + [ + 'fix', + FLAG_DRY_RUN, + '--package-managers', + 'NPM', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should accept --package-managers with single value', + async cmd => { + const { code, stdout } = await spawnSocketCli(binCliPath, cmd) + expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Not saving"`) + expect(code, 'should exit with code 0').toBe(0) + }, + ) + + cmdit( + [ + 'fix', + FLAG_DRY_RUN, + '--package-managers', + 'npm,pnpm', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should accept --package-managers comma-separated case-insensitive', + async cmd => { + const { code, stdout } = await spawnSocketCli(binCliPath, cmd) + expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Not saving"`) + expect(code, 'should exit with code 0').toBe(0) + }, + ) + + cmdit( + [ + 'fix', + FLAG_DRY_RUN, + '--package-managers', + 'NPM', + '--package-managers', + 'PNPM', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should accept multiple --package-managers flags', + async cmd => { + const { code, stdout } = await spawnSocketCli(binCliPath, cmd) + expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Not saving"`) + expect(code, 'should exit with code 0').toBe(0) + }, + ) + + cmdit( + [ + 'fix', + FLAG_DRY_RUN, + '--package-managers', + 'FOO', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should fail with invalid --package-managers value', + async cmd => { + const { code, stderr, stdout } = await spawnSocketCli(binCliPath, cmd) + const output = stdout + stderr + expect(output).toContain('Invalid package manager') + expect(code, 'should exit with non-zero code').not.toBe(0) + }, + ) + + cmdit( + [ + 'fix', + FLAG_DRY_RUN, + '--ecosystems', + 'npm', + '--package-managers', + 'PNPM', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should accept --ecosystems combined with --package-managers', + async cmd => { + const { code, stdout } = await spawnSocketCli(binCliPath, cmd) + expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Not saving"`) + expect(code, 'should exit with code 0').toBe(0) + }, + ) + }) + describe('--all flag behavior', () => { cmdit( ['fix', FLAG_DRY_RUN, '--all', FLAG_CONFIG, '{"apiToken":"fakeToken"}'], diff --git a/src/commands/fix/cmd-fix.mts b/src/commands/fix/cmd-fix.mts index dbedd4c44..c7c5d75b5 100644 --- a/src/commands/fix/cmd-fix.mts +++ b/src/commands/fix/cmd-fix.mts @@ -25,6 +25,10 @@ import { getFlagApiRequirementsOutput, getFlagListOutput, } from '../../utils/output-formatting.mts' +import { + ALL_PACKAGE_MANAGERS, + isValidPackageManager, +} from '../../utils/package-manager.mts' import { RangeStyles } from '../../utils/semver.mts' import { getDefaultOrgSlug } from '../ci/fetch-default-org-slug.mts' @@ -167,6 +171,13 @@ Available styles: 'Limit fix analysis to specific ecosystems. Can be provided as comma separated values or as multiple flags. Defaults to all ecosystems.', isMultiple: true, }, + packageManagers: { + type: 'string', + default: [], + description: + 'Limit fix analysis to specific package managers within an ecosystem (e.g. NPM, PNPM, YARN, MAVEN, POETRY). Accepts space- or comma-separated values and is case-insensitive. When combined with --ecosystems, an artifact must satisfy both filters.', + isMultiple: true, + }, showAffectedDirectDependencies: { type: 'boolean', default: false, @@ -311,6 +322,7 @@ async function run( maxSatisfying, minimumReleaseAge, outputFile, + packageManagers, prCheck, prLimit, rangeStyle, @@ -336,6 +348,7 @@ async function run( minSatisfying: boolean minimumReleaseAge: string outputFile: string + packageManagers: string[] prCheck: boolean prLimit: number rangeStyle: RangeStyle @@ -370,6 +383,24 @@ async function run( validatedEcosystems.push(ecosystem as PURL_Type) } + // Process and validate package manager values early, before dry-run check. + // Coana normalizes input to uppercase and rejects unknown values, so do the + // same here for a consistent UX and an early failure when invalid. + const packageManagersRaw = cmdFlagValueToArray(packageManagers).map(s => + s.toUpperCase(), + ) + const validatedPackageManagers: string[] = [] + for (const pm of packageManagersRaw) { + if (!isValidPackageManager(pm)) { + logger.fail( + `Invalid package manager: "${pm}". Valid values are: ${joinAnd([...ALL_PACKAGE_MANAGERS])}`, + ) + process.exitCode = 1 + return + } + validatedPackageManagers.push(pm) + } + // Collect ghsas early to validate --all and --id mutual exclusivity. const ghsas = arrayUnique([ ...cmdFlagValueToArray(cli.flags['id']), @@ -468,6 +499,7 @@ async function run( orgSlug, outputFile, outputKind, + packageManagers: validatedPackageManagers, prCheck, prLimit, rangeStyle, diff --git a/src/commands/fix/coana-fix.mts b/src/commands/fix/coana-fix.mts index d68d65e43..0cb5c4299 100644 --- a/src/commands/fix/coana-fix.mts +++ b/src/commands/fix/coana-fix.mts @@ -58,6 +58,7 @@ type DiscoverGhsaIdsOptions = { coanaVersion?: string | undefined cwd?: string | undefined ecosystems?: PURL_Type[] | undefined + packageManagers?: string[] | undefined silence?: boolean | undefined spinner?: Spinner | undefined } @@ -74,6 +75,7 @@ async function discoverGhsaIds( const { cwd = process.cwd(), ecosystems, + packageManagers, silence = false, spinner, } = { @@ -88,6 +90,9 @@ async function discoverGhsaIds( '--manifests-tar-hash', tarHash, ...(ecosystems?.length ? ['--purl-types', ...ecosystems] : []), + ...(packageManagers?.length + ? ['--package-managers', ...packageManagers] + : []), ], orgSlug, { @@ -129,6 +134,7 @@ export async function coanaFix( minimumReleaseAge, orgSlug, outputFile, + packageManagers, prLimit, showAffectedDirectDependencies, silence, @@ -250,6 +256,7 @@ export async function coanaFix( coanaVersion, cwd, ecosystems, + packageManagers, silence, spinner, }) @@ -284,6 +291,9 @@ export async function coanaFix( ...(include.length ? ['--include', ...include] : []), ...(exclude.length ? ['--exclude', ...exclude] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), + ...(packageManagers.length + ? ['--package-managers', ...packageManagers] + : []), ...(!applyFixes ? [FLAG_DRY_RUN] : []), '--output-file', tmpFile, @@ -381,6 +391,7 @@ export async function coanaFix( coanaVersion, cwd, ecosystems, + packageManagers, silence, spinner, }) @@ -442,6 +453,9 @@ export async function coanaFix( ...(include.length ? ['--include', ...include] : []), ...(exclude.length ? ['--exclude', ...exclude] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), + ...(packageManagers.length + ? ['--package-managers', ...packageManagers] + : []), ...(debug ? ['--debug'] : []), ...(disableExternalToolChecks ? ['--disable-external-tool-checks'] diff --git a/src/commands/fix/handle-fix.mts b/src/commands/fix/handle-fix.mts index c008c4dab..5ceda8e0b 100644 --- a/src/commands/fix/handle-fix.mts +++ b/src/commands/fix/handle-fix.mts @@ -131,6 +131,7 @@ export async function handleFix({ orgSlug, outputFile, outputKind, + packageManagers, prCheck, prLimit, rangeStyle, @@ -157,6 +158,7 @@ export async function handleFix({ minimumReleaseAge, outputFile, outputKind, + packageManagers, prCheck, prLimit, rangeStyle, @@ -184,6 +186,7 @@ export async function handleFix({ minSatisfying, orgSlug, outputFile, + packageManagers, prCheck, prLimit, rangeStyle, diff --git a/src/commands/fix/types.mts b/src/commands/fix/types.mts index 2109e5f89..fb73dd962 100644 --- a/src/commands/fix/types.mts +++ b/src/commands/fix/types.mts @@ -19,6 +19,7 @@ export type FixConfig = { minSatisfying: boolean orgSlug: string outputFile: string + packageManagers: string[] prCheck: boolean prLimit: number rangeStyle: RangeStyle diff --git a/src/utils/package-manager.mts b/src/utils/package-manager.mts new file mode 100644 index 000000000..ef5fc4bf9 --- /dev/null +++ b/src/utils/package-manager.mts @@ -0,0 +1,38 @@ +/** + * Package manager identifiers accepted by Coana's --package-managers filter. + * Used by `socket fix` to narrow fix computation to specific package managers + * within an ecosystem (e.g. only PNPM artifacts in a mixed pnpm/yarn/npm repo). + * + * Mirrors the list returned by Coana's `getFilterablePackageManagers()` in + * packages/web-compat-utils/src/package-manager-utils.ts. + */ + +export const ALL_PACKAGE_MANAGERS = [ + 'CARGO', + 'COMPOSER', + 'GO', + 'GRADLE', + 'MAVEN', + 'NPM', + 'NUGET', + 'PIPENV', + 'PIP_REQUIREMENTS', + 'PNPM', + 'POETRY', + 'RUBYGEMS', + 'RUSH', + 'SBT', + 'YARN', +] as const + +export type PackageManager = (typeof ALL_PACKAGE_MANAGERS)[number] + +const ALL_PACKAGE_MANAGERS_SET = new Set(ALL_PACKAGE_MANAGERS) + +export function getPackageManagerChoicesForMeow(): string[] { + return [...ALL_PACKAGE_MANAGERS] +} + +export function isValidPackageManager(value: string): value is PackageManager { + return ALL_PACKAGE_MANAGERS_SET.has(value) +} From 7f7b9e0a0a43fc7b1527b824f197b506a732703d Mon Sep 17 00:00:00 2001 From: Martin Torp Date: Thu, 30 Apr 2026 16:56:52 +0200 Subject: [PATCH 2/4] chore: bump @coana-tech/cli to 15.2.0 and add e2e tests for --package-managers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bump @coana-tech/cli from 15.1.0 to 15.2.0 (release containing the upstream --package-managers filter). - Bump CLI version 1.1.89 → 1.1.90 with a CHANGELOG entry covering both the new flag and the Coana version bump. - Add a real-Coana e2e fixture under test/fixtures/commands/fix/e2e-test-multipm with npm-managed lodash and pnpm-managed axios subprojects (lockfiles generated with the actual npm/pnpm tools). - Add three e2e cases: - `--package-managers NPM`: only the npm-managed lodash gets upgraded; pnpm-managed axios is left untouched. - `--package-managers PNPM`: only the pnpm-managed axios gets upgraded; npm-managed lodash is left untouched. - `--package-managers `: fails fast with the same friendly error path as the unit tests. --- CHANGELOG.md | 8 + package.json | 4 +- pnpm-lock.yaml | 10 +- src/commands/fix/cmd-fix.e2e.test.mts | 165 ++++++++++++++++++ .../npm-app/package-lock.json | 21 +++ .../fix/e2e-test-multipm/npm-app/package.json | 9 + .../e2e-test-multipm/pnpm-app/package.json | 9 + .../e2e-test-multipm/pnpm-app/pnpm-lock.yaml | 38 ++++ 8 files changed, 257 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/commands/fix/e2e-test-multipm/npm-app/package-lock.json create mode 100644 test/fixtures/commands/fix/e2e-test-multipm/npm-app/package.json create mode 100644 test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/package.json create mode 100644 test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/pnpm-lock.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index f6c5e01fc..6199c41f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [1.1.90](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.90) - 2026-04-30 + +### Added +- `socket fix` now accepts a `--package-managers` flag to narrow fix computation to specific package managers within an ecosystem (e.g. only PNPM in a monorepo that mixes pnpm/yarn/npm). Accepts space- or comma-separated values and is case-insensitive. When combined with `--ecosystems`, both filters must match. + +### Changed +- Updated the Coana CLI to v `15.2.0`. + ## [1.1.89](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.89) - 2026-04-30 ### Fixed diff --git a/package.json b/package.json index a6a80bff9..7aeae72e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket", - "version": "1.1.89", + "version": "1.1.90", "description": "CLI for Socket.dev", "homepage": "https://github.com/SocketDev/socket-cli", "license": "MIT AND OFL-1.1", @@ -97,7 +97,7 @@ "@babel/preset-typescript": "7.27.1", "@babel/runtime": "7.28.4", "@biomejs/biome": "2.2.4", - "@coana-tech/cli": "15.1.0", + "@coana-tech/cli": "15.2.0", "@cyclonedx/cdxgen": "12.1.2", "@dotenvx/dotenvx": "1.49.0", "@eslint/compat": "1.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19fd6fead..1ab849258 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,8 +128,8 @@ importers: specifier: 2.2.4 version: 2.2.4 '@coana-tech/cli': - specifier: 15.1.0 - version: 15.1.0 + specifier: 15.2.0 + version: 15.2.0 '@cyclonedx/cdxgen': specifier: 12.1.2 version: 12.1.2 @@ -749,8 +749,8 @@ packages: resolution: {integrity: sha512-hAs5PPKPCQ3/Nha+1fo4A4/gL85fIfxZwHPehsjCJ+BhQH2/yw6/xReuaPA/RfNQr6iz1PcD7BZcE3ctyyl3EA==} cpu: [x64] - '@coana-tech/cli@15.1.0': - resolution: {integrity: sha512-2lKo4A3c6WXR1AjQW+8feuiR+ltDn/5Y8P32zCY92Nyp3u3ARCke9iuePAQR+YBW0DI4xCckLlf9cU/jlobTHw==} + '@coana-tech/cli@15.2.0': + resolution: {integrity: sha512-vSAJH1GlGiDDuJArNSHcJkmbyN0hdXMnIs6VmtWYB0HoZSYkMwjgZVEyeeUWHNbnwk7fBpNcZd1cpBiUgp7bjw==} hasBin: true '@colors/colors@1.5.0': @@ -5385,7 +5385,7 @@ snapshots: '@cdxgen/cdxgen-plugins-bin@2.0.2': optional: true - '@coana-tech/cli@15.1.0': {} + '@coana-tech/cli@15.2.0': {} '@colors/colors@1.5.0': optional: true diff --git a/src/commands/fix/cmd-fix.e2e.test.mts b/src/commands/fix/cmd-fix.e2e.test.mts index 5298dd297..bbaea5a8c 100644 --- a/src/commands/fix/cmd-fix.e2e.test.mts +++ b/src/commands/fix/cmd-fix.e2e.test.mts @@ -470,6 +470,171 @@ describe('socket fix (E2E tests)', async () => { ) }) + describe('--package-managers filter', () => { + cmdit( + ['fix', '--package-managers', 'NPM', '.'], + 'should fix only the npm-managed artifact when --package-managers NPM is set', + async cmd => { + const tempFixture = await createTempFixtureCopy('e2e-test-multipm') + let stdout = '' + let stderr = '' + let code = -1 + + try { + const npmAppDir = path.join(tempFixture.path, 'npm-app') + const pnpmAppDir = path.join(tempFixture.path, 'pnpm-app') + + const beforeNpmPkg = await readPackageJson(npmAppDir) + const beforePnpmPkg = await readPackageJson(pnpmAppDir) + + expect(beforeNpmPkg.dependencies?.['lodash']).toBe('4.17.20') + expect(beforePnpmPkg.dependencies?.['axios']).toBe('0.21.0') + + const result = await spawnSocketCli(binCliPath, cmd, { + cwd: tempFixture.path, + env: getTestEnv(apiToken), + }) + stdout = result.stdout + stderr = result.stderr + code = result.code + + if (code !== 0) { + logCommandOutput(code, stdout, stderr) + } + + expect(code, 'should exit with code 0').toBe(0) + + const afterNpmPkg = await readPackageJson(npmAppDir) + const afterPnpmPkg = await readPackageJson(pnpmAppDir) + + // npm-app's lodash should be upgraded. + const afterLodash = afterNpmPkg.dependencies?.['lodash'] + expect(afterLodash).toBeDefined() + expect( + compareVersions(extractVersion(afterLodash!), '4.17.20'), + `lodash should be upgraded from 4.17.20 to ${afterLodash}`, + ).toBeGreaterThan(0) + + // pnpm-app's axios should remain unchanged (filtered out by --package-managers NPM). + expect( + afterPnpmPkg.dependencies?.['axios'], + 'pnpm-app axios should not be touched when --package-managers NPM is set', + ).toBe('0.21.0') + + logger.info( + `\n--package-managers NPM upgraded npm-app lodash to ${afterLodash} and left pnpm-app axios untouched`, + ) + } catch (e) { + if (code !== 0) { + logCommandOutput(code, stdout, stderr) + } + throw e + } finally { + await tempFixture.cleanup() + } + }, + { timeout: testTimeout }, + ) + + cmdit( + ['fix', '--package-managers', 'PNPM', '.'], + 'should fix only the pnpm-managed artifact when --package-managers PNPM is set', + async cmd => { + const tempFixture = await createTempFixtureCopy('e2e-test-multipm') + let stdout = '' + let stderr = '' + let code = -1 + + try { + const npmAppDir = path.join(tempFixture.path, 'npm-app') + const pnpmAppDir = path.join(tempFixture.path, 'pnpm-app') + + const beforeNpmPkg = await readPackageJson(npmAppDir) + const beforePnpmPkg = await readPackageJson(pnpmAppDir) + + expect(beforeNpmPkg.dependencies?.['lodash']).toBe('4.17.20') + expect(beforePnpmPkg.dependencies?.['axios']).toBe('0.21.0') + + const result = await spawnSocketCli(binCliPath, cmd, { + cwd: tempFixture.path, + env: getTestEnv(apiToken), + }) + stdout = result.stdout + stderr = result.stderr + code = result.code + + if (code !== 0) { + logCommandOutput(code, stdout, stderr) + } + + expect(code, 'should exit with code 0').toBe(0) + + const afterNpmPkg = await readPackageJson(npmAppDir) + const afterPnpmPkg = await readPackageJson(pnpmAppDir) + + // pnpm-app's axios should be upgraded. + const afterAxios = afterPnpmPkg.dependencies?.['axios'] + expect(afterAxios).toBeDefined() + expect( + compareVersions(extractVersion(afterAxios!), '0.21.0'), + `axios should be upgraded from 0.21.0 to ${afterAxios}`, + ).toBeGreaterThan(0) + + // npm-app's lodash should remain unchanged (filtered out by --package-managers PNPM). + expect( + afterNpmPkg.dependencies?.['lodash'], + 'npm-app lodash should not be touched when --package-managers PNPM is set', + ).toBe('4.17.20') + + logger.info( + `\n--package-managers PNPM upgraded pnpm-app axios to ${afterAxios} and left npm-app lodash untouched`, + ) + } catch (e) { + if (code !== 0) { + logCommandOutput(code, stdout, stderr) + } + throw e + } finally { + await tempFixture.cleanup() + } + }, + { timeout: testTimeout }, + ) + + cmdit( + ['fix', '--package-managers', 'NOT_A_REAL_PM', '.'], + 'should fail fast with a clear error when --package-managers value is invalid', + async cmd => { + const tempFixture = await createTempFixtureCopy('e2e-test-multipm') + let stdout = '' + let stderr = '' + let code = -1 + + try { + const result = await spawnSocketCli(binCliPath, cmd, { + cwd: tempFixture.path, + env: getTestEnv(apiToken), + }) + stdout = result.stdout + stderr = result.stderr + code = result.code + + const output = stdout + stderr + expect(output).toContain('Invalid package manager') + expect(code, 'should exit with non-zero code').not.toBe(0) + } catch (e) { + if (code === 0) { + logCommandOutput(code, stdout, stderr) + } + throw e + } finally { + await tempFixture.cleanup() + } + }, + { timeout: testTimeout }, + ) + }) + describe('Python projects', () => { cmdit( ['fix', '.'], diff --git a/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package-lock.json b/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package-lock.json new file mode 100644 index 000000000..eb140badb --- /dev/null +++ b/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "e2e-test-multipm-npm", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "e2e-test-multipm-npm", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.20" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "license": "MIT" + } + } +} diff --git a/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package.json b/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package.json new file mode 100644 index 000000000..eb083ee27 --- /dev/null +++ b/test/fixtures/commands/fix/e2e-test-multipm/npm-app/package.json @@ -0,0 +1,9 @@ +{ + "name": "e2e-test-multipm-npm", + "version": "1.0.0", + "description": "E2E test fixture (npm-managed) with vulnerable lodash", + "main": "index.js", + "dependencies": { + "lodash": "4.17.20" + } +} diff --git a/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/package.json b/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/package.json new file mode 100644 index 000000000..d156d65d2 --- /dev/null +++ b/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/package.json @@ -0,0 +1,9 @@ +{ + "name": "e2e-test-multipm-pnpm", + "version": "1.0.0", + "description": "E2E test fixture (pnpm-managed) with vulnerable axios", + "main": "index.js", + "dependencies": { + "axios": "0.21.0" + } +} diff --git a/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/pnpm-lock.yaml b/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/pnpm-lock.yaml new file mode 100644 index 000000000..61b8666d5 --- /dev/null +++ b/test/fixtures/commands/fix/e2e-test-multipm/pnpm-app/pnpm-lock.yaml @@ -0,0 +1,38 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + axios: + specifier: 0.21.0 + version: 0.21.0 + +packages: + + axios@0.21.0: + resolution: {integrity: sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==} + deprecated: Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410 + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + +snapshots: + + axios@0.21.0: + dependencies: + follow-redirects: 1.16.0 + transitivePeerDependencies: + - debug + + follow-redirects@1.16.0: {} From 0d4602041aaa839c52458e180bd27d8f1a9d3ff8 Mon Sep 17 00:00:00 2001 From: Martin Torp Date: Thu, 30 Apr 2026 17:54:09 +0200 Subject: [PATCH 3/4] fix(test): add packageManagers to handle-fix-limit FixConfig mock The baseConfig in handle-fix-limit.test.mts is missing the new packageManagers field, which caused a TypeError ("Cannot read properties of undefined (reading 'length')") when coana-fix.mts evaluates packageManagers.length on the spread mock. Add packageManagers: [] alongside the existing array fields. --- src/commands/fix/handle-fix-limit.test.mts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/fix/handle-fix-limit.test.mts b/src/commands/fix/handle-fix-limit.test.mts index 7028d02f8..f861df735 100644 --- a/src/commands/fix/handle-fix-limit.test.mts +++ b/src/commands/fix/handle-fix-limit.test.mts @@ -86,6 +86,7 @@ describe('socket fix --pr-limit behavior verification', () => { minimumReleaseAge: '', orgSlug: 'test-org', outputFile: '', + packageManagers: [], prCheck: true, prLimit: 10, rangeStyle: 'preserve', From f4627edaf73b7af478adf8ec68219b84a006fc73 Mon Sep 17 00:00:00 2001 From: Martin Torp Date: Thu, 30 Apr 2026 18:12:51 +0200 Subject: [PATCH 4/4] refactor: drop unused getPackageManagerChoicesForMeow helper Bugbot caught this: the helper was exported but never imported. cmd-fix.mts spreads ALL_PACKAGE_MANAGERS directly when building the validation error message, so the helper added no value. --- src/utils/package-manager.mts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/package-manager.mts b/src/utils/package-manager.mts index ef5fc4bf9..42b9dcef7 100644 --- a/src/utils/package-manager.mts +++ b/src/utils/package-manager.mts @@ -29,10 +29,6 @@ export type PackageManager = (typeof ALL_PACKAGE_MANAGERS)[number] const ALL_PACKAGE_MANAGERS_SET = new Set(ALL_PACKAGE_MANAGERS) -export function getPackageManagerChoicesForMeow(): string[] { - return [...ALL_PACKAGE_MANAGERS] -} - export function isValidPackageManager(value: string): value is PackageManager { return ALL_PACKAGE_MANAGERS_SET.has(value) }