Skip to content

Commit 10fe89e

Browse files
authored
fix(scan): ignore project .pnpmfile.cjs when launching tools via pnpm dlx (1.1.130) (#1383)
Reachability scans launch Coana (and cdxgen/synp) via `pnpm dlx` with the target repo as cwd. In a pnpm workspace root, `pnpm dlx` evaluates that repo's root `.pnpmfile.cjs`, so a broken or environment-specific hook there (e.g. a `require()` of a file that is still an unresolved Git LFS pointer) crashes the launcher with a bare exit code before the tool ever starts. Set `npm_config_ignore_pnpmfile=true` on the pnpm dlx launch env so the project's pnpm hooks never run. The dlx tool installs into an isolated store, so those hooks are irrelevant to it. The `--ignore-pnpmfile` CLI flag is rejected by `pnpm dlx`; only the env/config form works.
1 parent 3132ccf commit 10fe89e

4 files changed

Lines changed: 44 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [1.1.130](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.130) - 2026-06-29
8+
9+
### Fixed
10+
- Reachability analysis no longer fails to start in pnpm workspaces that define a `.pnpmfile.cjs`. Socket now launches its bundled analysis tools without running the project's pnpm hooks, so a broken or environment-specific hook (for example, one that loads a file managed by Git LFS) can no longer stop a scan before it begins.
11+
712
## [1.1.129](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.129) - 2026-06-26
813

914
### Changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "socket",
3-
"version": "1.1.129",
3+
"version": "1.1.130",
44
"description": "CLI for Socket.dev",
55
"homepage": "https://github.com/SocketDev/socket-cli",
66
"license": "MIT",

src/utils/dlx.mts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,26 @@ export async function spawnDlx(
128128
spawnArgs.push(FLAG_SILENT)
129129
}
130130
spawnArgs.push('dlx')
131+
// Never let the target project's `.pnpmfile.cjs` hooks run while we launch
132+
// a third-party tool via `pnpm dlx`. In a pnpm workspace root, `pnpm dlx`
133+
// loads the cwd's `.pnpmfile.cjs`, so a broken hook there (e.g. a `require`
134+
// of an unresolved Git LFS pointer) crashes the launcher with a bare exit
135+
// code before our tool ever starts. The dlx tool installs into an isolated
136+
// store, so the project's install hooks are irrelevant to it. pnpm honors
137+
// this only as a config setting, not as a `dlx` CLI flag, so it must be set
138+
// via the npm_config_ env var. See: https://pnpm.io/npmrc#settings
139+
const pnpmEnv: Record<string, string | undefined> = {
140+
...getOwn(finalShadowOptions, 'env'),
141+
npm_config_ignore_pnpmfile: 'true',
142+
}
131143
if (force) {
132-
// For pnpm, set dlx-cache-max-age to 0 via env to force fresh download.
133-
// This ensures we always get the latest version within the range.
134-
finalShadowOptions = {
135-
...finalShadowOptions,
136-
env: {
137-
...getOwn(finalShadowOptions, 'env'),
138-
// Set dlx cache max age to 0 minutes to bypass cache.
139-
// The npm_config_ prefix is how pnpm reads config from environment variables.
140-
// See: https://pnpm.io/npmrc#settings
141-
npm_config_dlx_cache_max_age: '0',
142-
},
143-
}
144+
// Set dlx-cache-max-age to 0 minutes to bypass cache and force a fresh
145+
// download. This ensures we always get the latest version within the range.
146+
pnpmEnv['npm_config_dlx_cache_max_age'] = '0'
147+
}
148+
finalShadowOptions = {
149+
...finalShadowOptions,
150+
env: pnpmEnv,
144151
}
145152
spawnArgs.push(packageString, ...args)
146153

src/utils/dlx.test.mts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,25 @@ describe('utils/dlx', () => {
181181
expect(options.env.npm_config_dlx_cache_max_age).toBe('0')
182182
})
183183

184+
it('should set npm_config_ignore_pnpmfile env var for pnpm regardless of force', async () => {
185+
const packageSpec: DlxPackageSpec = {
186+
name: '@coana-tech/cli',
187+
version: '1.0.0',
188+
}
189+
190+
// force defaults to false here, exercising the non-force path.
191+
await spawnDlx(packageSpec, ['run', '/some/path'], { agent: 'pnpm' })
192+
193+
expect(mockShadowPnpmBin).toHaveBeenCalledTimes(1)
194+
const [, options] = mockShadowPnpmBin.mock.calls[0]
195+
196+
// The target project's `.pnpmfile.cjs` must be ignored so a broken hook
197+
// (e.g. a require of an unresolved Git LFS pointer) cannot crash the
198+
// `pnpm dlx` launcher before the tool starts.
199+
expect(options.env).toBeDefined()
200+
expect(options.env.npm_config_ignore_pnpmfile).toBe('true')
201+
})
202+
184203
it('should handle pinned version without silent flag by default', async () => {
185204
const packageSpec: DlxPackageSpec = {
186205
name: '@coana-tech/cli',

0 commit comments

Comments
 (0)