diff --git a/patches/backported-patches.json b/patches/backported-patches.json index 204fee8..fdede1f 100644 --- a/patches/backported-patches.json +++ b/patches/backported-patches.json @@ -140,5 +140,17 @@ "patch_path": "patches/web-server/webview.diff", "link": "https://github.com/microsoft/vscode/commit/236fa7d8ea86f0f4261df38e1a17b3c7e7002bd0", "note": "Already mitigated by existing webview.diff: in the non-validated iframe path parentOrigin is forced to window.origin before start(), so an attacker-supplied parentOrigin search param is never honored (onmessage only accepts event.origin === parentOrigin). Equivalent to upstream's explicit parentOrigin rejection." + }, + { + "finding_id": "CVE-2026-70334", + "affected_versions": "< 1.136.2", + "patch_path": "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": "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..1b65e8c --- /dev/null +++ b/patches/common/fix-config-nested-restricted-settings.diff @@ -0,0 +1,77 @@ +From: Sandeep Somavarapu +Subject: Filter restricted settings in nested configuration objects +Origin: upstream, 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. 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 +@@ -441,12 +441,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, excludedConfigurationProperties, options)) { +- raw[key] = properties[key]; ++ const result = this.filterProperty(key, properties[key], configurationProperties, excludedConfigurationProperties, options); ++ restricted.push(...result.restricted); ++ hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties; ++ if (result.included) { ++ raw[key] = result.value; + } else { + hasExcludedProperties = true; + } +@@ -455,6 +454,46 @@ export class ConfigurationModelParser { + return { raw, restricted, hasExcludedProperties }; + } + ++ private filterProperty(path: string, value: unknown, configurationProperties: IStringDictionary, excludedConfigurationProperties: IStringDictionary, options: ConfigurationParseOptions): { included: boolean; value: unknown; restricted: string[]; hasExcludedProperties: boolean } { ++ const propertySchema = configurationProperties[path]; ++ if (propertySchema) { ++ return { included: this.shouldInclude(path, propertySchema, excludedConfigurationProperties, options), value, restricted: propertySchema.restricted ? [path] : [], hasExcludedProperties: false }; ++ } ++ if (!types.isObject(value) || Array.isArray(value)) { ++ return { included: this.shouldInclude(path, propertySchema, excludedConfigurationProperties, options), value, restricted: [], hasExcludedProperties: false }; ++ } ++ // Excluded properties can themselves be object-typed (e.g. `mcp.enterpriseManagedAuth.idp`), so treat them as a leaf too. ++ if (excludedConfigurationProperties[path]) { ++ return { included: this.shouldInclude(path, propertySchema, excludedConfigurationProperties, 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, excludedConfigurationProperties, 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, excludedConfigurationProperties, 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, excludedConfigurationProperties: IStringDictionary, options: ConfigurationParseOptions): boolean { + if (options.exclude?.includes(key)) { + return false; diff --git a/patches/sagemaker.series b/patches/sagemaker.series index 3a5a403..a3db74f 100644 --- a/patches/sagemaker.series +++ b/patches/sagemaker.series @@ -64,3 +64,4 @@ common/add-openvsx-verification-check.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 b4a3f78..3055976 100644 --- a/patches/web-embedded-with-terminal.series +++ b/patches/web-embedded-with-terminal.series @@ -60,3 +60,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 6c0d91d..a33baed 100644 --- a/patches/web-embedded.series +++ b/patches/web-embedded.series @@ -63,3 +63,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 41ca9dd..a71653a 100644 --- a/patches/web-server.series +++ b/patches/web-server.series @@ -44,3 +44,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