From 1ee33d0aed9380a032639c4c03997b9bbbdc36ec Mon Sep 17 00:00:00 2001 From: Sergey Kazantsev Date: Fri, 23 Oct 2026 08:39:05 +0000 Subject: [PATCH] fix: Harden configuration parsing for nested settings --- patches/backported-patches.json | 12 +++ ...fix-config-nested-restricted-settings.diff | 74 +++++++++++++++++++ patches/sagemaker.series | 1 + patches/web-embedded-with-terminal.series | 1 + patches/web-embedded.series | 1 + patches/web-server.series | 1 + 6 files changed, 90 insertions(+) create mode 100644 patches/common/fix-config-nested-restricted-settings.diff diff --git a/patches/backported-patches.json b/patches/backported-patches.json index 18b4318..c1892a7 100644 --- a/patches/backported-patches.json +++ b/patches/backported-patches.json @@ -136,5 +136,17 @@ "patch_path": "patches/web-server/webview.diff", "link": "https://github.com/microsoft/vscode/commit/236fa7d8ea86f0f4261df38e1a17b3c7e7002bd0", "note": "webWorkerExtensionHostIframe.html hardening already shipped: in the non-validated hostname path parentOrigin is forced to window.origin and the attacker-supplied parentOrigin search param is never used, equivalent to upstream's explicit parentOrigin rejection" + }, + { + "finding_id": "CVE-2026-70334", + "affected_versions": "< 1.136.2", + "patch_path": "patches/common/fix-config-nested-restricted-settings.diff", + "link": "https://github.com/microsoft/vscode/commit/0684cb5905a3f23156f45a28135326e09310ff4d" + }, + { + "finding_id": "GHSA-q2f8-hh8x-wpc2", + "affected_versions": "< 1.136.2", + "patch_path": "patches/common/fix-config-nested-restricted-settings.diff", + "link": "https://github.com/microsoft/vscode/commit/0684cb5905a3f23156f45a28135326e09310ff4d" } ] diff --git a/patches/common/fix-config-nested-restricted-settings.diff b/patches/common/fix-config-nested-restricted-settings.diff new file mode 100644 index 0000000..3d66061 --- /dev/null +++ b/patches/common/fix-config-nested-restricted-settings.diff @@ -0,0 +1,74 @@ +From: Sandeep Somavarapu +Subject: Filter restricted settings in nested configuration objects +Origin: backport, https://github.com/microsoft/vscode/commit/0684cb5905a3f23156f45a28135326e09310ff4d +Bug: GHSA-q2f8-hh8x-wpc2 + +ConfigurationModelParser only checked top-level keys against the +configuration registry. Walk nested objects and check each setting by its +effective dotted path. Adapted for 1.101.x, which has no excluded-property +filtering in the parser. Remove when Code-OSS is updated to >= 1.136.2. +Index: code-editor-src/src/vs/platform/configuration/common/configurationModels.ts +=================================================================== +--- code-editor-src.orig/src/vs/platform/configuration/common/configurationModels.ts ++++ code-editor-src/src/vs/platform/configuration/common/configurationModels.ts +@@ -428,12 +428,11 @@ export class ConfigurationModelParser { + hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties; + restricted.push(...result.restricted); + } else { +- const propertySchema = configurationProperties[key]; +- if (propertySchema?.restricted) { +- restricted.push(key); +- } +- if (this.shouldInclude(key, propertySchema, options)) { +- raw[key] = properties[key]; ++ const result = this.filterProperty(key, properties[key], configurationProperties, options); ++ restricted.push(...result.restricted); ++ hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties; ++ if (result.included) { ++ raw[key] = result.value; + } else { + hasExcludedProperties = true; + } +@@ -442,6 +441,42 @@ export class ConfigurationModelParser { + return { raw, restricted, hasExcludedProperties }; + } + ++ private filterProperty(path: string, value: unknown, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema | undefined }, options: ConfigurationParseOptions): { included: boolean; value: unknown; restricted: string[]; hasExcludedProperties: boolean } { ++ const propertySchema = configurationProperties[path]; ++ if (propertySchema) { ++ return { included: this.shouldInclude(path, propertySchema, options), value, restricted: propertySchema.restricted ? [path] : [], hasExcludedProperties: false }; ++ } ++ if (!types.isObject(value) || Array.isArray(value)) { ++ return { included: this.shouldInclude(path, propertySchema, options), value, restricted: [], hasExcludedProperties: false }; ++ } ++ // If the whole object is explicitly excluded, do not recurse into its children. ++ if (options.exclude?.includes(path)) { ++ return { included: false, value, restricted: [], hasExcludedProperties: false }; ++ } ++ const keys = Object.keys(value); ++ if (keys.length === 0) { ++ return { included: this.shouldInclude(path, propertySchema, options), value, restricted: [], hasExcludedProperties: false }; ++ } ++ const nested: IStringDictionary = {}; ++ const restricted: string[] = []; ++ let included = false; ++ let hasExcludedProperties = false; ++ for (const key of keys) { ++ const result = this.filterProperty(`${path}.${key}`, (value as IStringDictionary)[key], configurationProperties, options); ++ if (result.restricted.length) { ++ restricted.push(...result.restricted); ++ } ++ hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties; ++ if (result.included) { ++ nested[key] = result.value; ++ included = true; ++ } else { ++ hasExcludedProperties = true; ++ } ++ } ++ return { included, value: nested, restricted, hasExcludedProperties }; ++ } ++ + private shouldInclude(key: string, propertySchema: IConfigurationPropertySchema | undefined, options: ConfigurationParseOptions): boolean { + if (options.exclude?.includes(key)) { + return false; diff --git a/patches/sagemaker.series b/patches/sagemaker.series index ac28449..51c04a8 100644 --- a/patches/sagemaker.series +++ b/patches/sagemaker.series @@ -61,3 +61,4 @@ sagemaker/remove-delay-shutdown-endpoint.diff common/finding-override-undici.diff common/finding-override-ws.diff common/finding-override-tar.diff +common/fix-config-nested-restricted-settings.diff diff --git a/patches/web-embedded-with-terminal.series b/patches/web-embedded-with-terminal.series index e015869..b55832b 100644 --- a/patches/web-embedded-with-terminal.series +++ b/patches/web-embedded-with-terminal.series @@ -58,3 +58,4 @@ web-embedded/only-allow-trusted-origins-in-webviews.diff common/finding-override-undici.diff common/finding-override-ws.diff common/finding-override-tar.diff +common/fix-config-nested-restricted-settings.diff diff --git a/patches/web-embedded.series b/patches/web-embedded.series index f92166d..7a8e6d0 100644 --- a/patches/web-embedded.series +++ b/patches/web-embedded.series @@ -60,3 +60,4 @@ web-embedded/enable-ts-features.diff common/finding-override-undici.diff common/finding-override-ws.diff common/finding-override-tar.diff +common/fix-config-nested-restricted-settings.diff diff --git a/patches/web-server.series b/patches/web-server.series index 593a9bc..a8f4f21 100644 --- a/patches/web-server.series +++ b/patches/web-server.series @@ -42,3 +42,4 @@ web-server/signature-verification.diff common/finding-override-undici.diff common/finding-override-ws.diff common/finding-override-tar.diff +common/fix-config-nested-restricted-settings.diff