fix: reject invalid overrides values (#11380)

* fix: reject invalid overrides values

* fix: improve overrides validation error messages
This commit is contained in:
Dami Oyeniyi
2026-05-05 00:06:33 +01:00
committed by Zoltan Kochan
parent 8fdd9a9a6f
commit 5f34a8d028
3 changed files with 55 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/config.reader": patch
"pnpm": patch
---
Throw a pnpm error when `overrides` has an invalid shape or contains a non-string value.

View File

@@ -28,6 +28,7 @@ export type OptionsFromRootManifest = {
export function getOptionsFromPnpmSettings (manifestDir: string | undefined, pnpmSettings: PnpmSettings, manifest?: ProjectManifest): OptionsFromRootManifest {
const settings: OptionsFromRootManifest = replaceEnvInSettings(pnpmSettings)
if (settings.overrides) {
assertValidOverrides(settings.overrides)
if (Object.keys(settings.overrides).length === 0) {
delete settings.overrides
} else if (manifest) {
@@ -45,6 +46,23 @@ export function getOptionsFromPnpmSettings (manifestDir: string | undefined, pnp
return settings
}
function assertValidOverrides (overrides: unknown): asserts overrides is Record<string, string> {
if (overrides == null || typeof overrides !== 'object' || Array.isArray(overrides)) {
throw new PnpmError('INVALID_OVERRIDES', `The overrides field should be an object, but got ${renderReceivedType(overrides)}`)
}
for (const [selector, spec] of Object.entries(overrides)) {
if (typeof spec !== 'string') {
throw new PnpmError('INVALID_OVERRIDES', `The value of overrides.${selector} should be a string, but got ${renderReceivedType(spec)}`)
}
}
}
function renderReceivedType (value: unknown): string {
if (value === null) return 'null'
if (Array.isArray(value)) return 'array'
return typeof value
}
function replaceEnvInSettings (settings: PnpmSettings): PnpmSettings {
const newSettings: PnpmSettings = {}
for (const [key, value] of Object.entries(settings)) {

View File

@@ -33,3 +33,34 @@ test('getOptionsFromPnpmSettings() converts allowBuilds', () => {
},
})
})
test('getOptionsFromPnpmSettings() rejects non-string overrides values', () => {
expect(() => getOptionsFromPnpmSettings(process.cwd(), {
overrides: {
foo: null,
} as unknown as Record<string, string>,
})).toThrow(expect.objectContaining({
code: 'ERR_PNPM_INVALID_OVERRIDES',
message: 'The value of overrides.foo should be a string, but got null',
}))
})
test('getOptionsFromPnpmSettings() rejects array overrides values', () => {
expect(() => getOptionsFromPnpmSettings(process.cwd(), {
overrides: {
foo: [],
} as unknown as Record<string, string>,
})).toThrow(expect.objectContaining({
code: 'ERR_PNPM_INVALID_OVERRIDES',
message: 'The value of overrides.foo should be a string, but got array',
}))
})
test('getOptionsFromPnpmSettings() rejects non-object overrides values', () => {
expect(() => getOptionsFromPnpmSettings(process.cwd(), {
overrides: [] as unknown as Record<string, string>,
})).toThrow(expect.objectContaining({
code: 'ERR_PNPM_INVALID_OVERRIDES',
message: 'The overrides field should be an object, but got array',
}))
})