From 5bf2e380264286b5b72f0e7a1c56e98c34f2d6f3 Mon Sep 17 00:00:00 2001 From: adilburaksen Date: Sat, 16 May 2026 21:57:16 +0300 Subject: [PATCH 1/2] fix: validate devtoolsOptionsUri scheme and filename in extensionEnabledState handleExtensionEnabledState() accepted the devtoolsOptionsUri query parameter without validation and passed it directly to DevToolsOptions.setExtensionEnabledState(), which creates the file and parent directories if they do not exist. An untrusted caller could supply an arbitrary file: URI to create or overwrite any path writable by the DevTools server process. Add a guard that rejects URIs whose scheme is not 'file' or whose path does not end with 'devtools_options.yaml'. Both conditions must hold for a legitimate devtools options file. --- .../src/server/handlers/_devtools_extensions.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart b/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart index f7c63671630..324fd30e8c4 100644 --- a/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart +++ b/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart @@ -80,6 +80,19 @@ extension _ExtensionsApiHandler on Never { final devtoolsOptionsFileUriString = queryParams[ExtensionsApi.devtoolsOptionsUriPropertyName]!; final devtoolsOptionsFileUri = Uri.parse(devtoolsOptionsFileUriString); + + // Validate that the URI is a local file URI pointing to a + // 'devtools_options.yaml' file. Accepting arbitrary URIs from the query + // string would allow an untrusted caller to create or overwrite any file + // writable by the DevTools server process. + if (devtoolsOptionsFileUri.scheme != 'file' || + !devtoolsOptionsFileUri.path.endsWith('devtools_options.yaml')) { + return api.badRequest( + 'Invalid devtoolsOptionsUri: must be a file: URI ending in ' + "'devtools_options.yaml'.", + ); + } + final extensionName = queryParams[ExtensionsApi.extensionNamePropertyName]!; final activate = queryParams[ExtensionsApi.enabledStatePropertyName]; From 1fe700ff955a17f7d2ae93936e0d89186ec838cf Mon Sep 17 00:00:00 2001 From: adilburaksen Date: Sat, 16 May 2026 22:10:12 +0300 Subject: [PATCH 2/2] fix: restrict devtools_options.yaml path check to exact filename endsWith('devtools_options.yaml') matched paths like 'not_devtools_options.yaml'. Adding the path separator prefix ensures only files literally named 'devtools_options.yaml' are accepted. --- .../lib/src/server/handlers/_devtools_extensions.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart b/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart index 324fd30e8c4..b5b10bbd8a6 100644 --- a/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart +++ b/packages/devtools_shared/lib/src/server/handlers/_devtools_extensions.dart @@ -86,7 +86,7 @@ extension _ExtensionsApiHandler on Never { // string would allow an untrusted caller to create or overwrite any file // writable by the DevTools server process. if (devtoolsOptionsFileUri.scheme != 'file' || - !devtoolsOptionsFileUri.path.endsWith('devtools_options.yaml')) { + !devtoolsOptionsFileUri.path.endsWith('/devtools_options.yaml')) { return api.badRequest( 'Invalid devtoolsOptionsUri: must be a file: URI ending in ' "'devtools_options.yaml'.",