diff --git a/patches/backported-patches.json b/patches/backported-patches.json index bd382dd..bf19ec8 100644 --- a/patches/backported-patches.json +++ b/patches/backported-patches.json @@ -88,5 +88,17 @@ "patch_path": "patches/web-server/webview.diff", "link": "https://github.com/microsoft/vscode/commit/236fa7d8ea86f0f4261df38e1a17b3c7e7002bd0", "note": "RCE via attacker-controlled parentOrigin in webWorkerExtensionHostIframe.html. Already mitigated by the existing web-server/webview.diff (repo commit 4d1c2d6): the non-validated path forces parentOrigin = window.origin and never reads the attacker-supplied searchParams value there, while the hostname-validation path binds parentOrigin into the parentOriginHash subdomain check that rejects any mismatched origin. Equivalent to upstream's explicit parentOrigin rejection; not double-applied." + }, + { + "finding_id": "CVE-2026-70334", + "affected_versions": "< 1.136.2", + "patch_path": "patches/common/ghsa-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/ghsa-config-nested-restricted-settings.diff", + "link": "https://github.com/microsoft/vscode/commit/0684cb5905a3f23156f45a28135326e09310ff4d" } ] diff --git a/patches/common/ghsa-config-nested-restricted-settings.diff b/patches/common/ghsa-config-nested-restricted-settings.diff new file mode 100644 index 0000000..1b65e8c --- /dev/null +++ b/patches/common/ghsa-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 f5e2c94..6ee9276 100644 --- a/patches/sagemaker.series +++ b/patches/sagemaker.series @@ -73,3 +73,4 @@ common/finding-override-undici.diff common/finding-override-form-data.diff common/finding-override-tar.diff common/copilot-restrict-debug-override-urls-to-user-scope.diff +common/ghsa-config-nested-restricted-settings.diff diff --git a/patches/web-embedded-with-terminal.series b/patches/web-embedded-with-terminal.series index 8e16591..a35f896 100644 --- a/patches/web-embedded-with-terminal.series +++ b/patches/web-embedded-with-terminal.series @@ -70,3 +70,4 @@ common/finding-override-undici.diff common/finding-override-form-data.diff common/finding-override-tar.diff common/copilot-restrict-debug-override-urls-to-user-scope.diff +common/ghsa-config-nested-restricted-settings.diff diff --git a/patches/web-embedded.series b/patches/web-embedded.series index 915d0b6..afe3ac0 100644 --- a/patches/web-embedded.series +++ b/patches/web-embedded.series @@ -73,3 +73,4 @@ common/finding-override-undici.diff common/finding-override-form-data.diff common/finding-override-tar.diff common/copilot-restrict-debug-override-urls-to-user-scope.diff +common/ghsa-config-nested-restricted-settings.diff diff --git a/patches/web-server.series b/patches/web-server.series index 09484d2..9f1347a 100644 --- a/patches/web-server.series +++ b/patches/web-server.series @@ -52,3 +52,4 @@ common/finding-override-undici.diff common/finding-override-form-data.diff common/finding-override-tar.diff common/copilot-restrict-debug-override-urls-to-user-scope.diff +common/ghsa-config-nested-restricted-settings.diff