From 2e6adf8a6dc32191c9615d11ea0081b4568f2aa0 Mon Sep 17 00:00:00 2001 From: pomelo-nwu Date: Tue, 19 May 2026 15:41:35 +0800 Subject: [PATCH] fix(cli): guard mock setValue against prototype pollution in adapter test CodeQL flagged the mock setValue's recursive property assignment as a prototype-pollution sink. Add UNSAFE_KEY_PARTS check at the top of the mock to align with the real setNestedPropertySafe contract. Co-authored-by: Qwen-Coder --- packages/cli/src/config/loadedSettingsAdapter.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/cli/src/config/loadedSettingsAdapter.test.ts b/packages/cli/src/config/loadedSettingsAdapter.test.ts index 973e93a2f..689d2379b 100644 --- a/packages/cli/src/config/loadedSettingsAdapter.test.ts +++ b/packages/cli/src/config/loadedSettingsAdapter.test.ts @@ -43,9 +43,19 @@ function makeSettings(initial: SettingsShape = {}) { originalSettings: structuredClone(initial), path: '/tmp/qwen-test-settings.json', }; + // Mirror the real LoadedSettings/setNestedPropertySafe contract: any caller + // that slipped a `__proto__` / `constructor` / `prototype` segment past the + // adapter-layer guard would have its write rejected here too. The adapter + // already short-circuits these (see the test below), but guarding the mock + // keeps it semantically aligned with the production helper and quiets + // CodeQL's prototype-pollution scanner on the mock fixture itself. + const UNSAFE_KEY_PARTS = new Set(['__proto__', 'constructor', 'prototype']); const setValue = vi.fn( (_scope: SettingScope, key: string, value: unknown) => { const parts = key.split('.'); + if (parts.some((p) => UNSAFE_KEY_PARTS.has(p))) { + throw new Error(`mock setValue refused reserved segment in: ${key}`); + } let current: Record = file.settings as Record< string, unknown