Information disclosure

MEDIUM
flutter/flutter
Commit: da2864adacf1
Affected: Pre-fix Flutter tools versions prior to v1.16.3 (i.e., < v1.16.3)
2026-05-01 15:28 UTC

Description

The commit eliminates a bespoke shelf middleware that served the contents of dwds/src/injected/client.js by reading the file from disk and returning it in the HTTP response. This custom path could expose the contents of an internal injected client script if accessed by a client, constituting an information-disclosure risk. By removing the disk-read path and relying on the standard dwds handler, the fix reduces the surface for leaking internal assets. The change is accompanied by a dependency bump to dwds 27.1.1, indicating both a refactor and vulnerability-related hardening.

Proof of Concept

PoC steps (pre-fix behavior): 1) Run a Flutter web project with a toolchain containing the vulnerable code path (pre-fix). 2) Start the dev server (the port is printed in logs, or you can identify it via lsof/netstat). 3) Issue an HTTP GET request to the asset URL that used to be intercepted by the custom handler, for example: http://localhost:<port>/dwds/src/injected/client.js 4) Observe the response containing the raw contents of the injected/client.js file from the dwds package on disk, exposing internal implementation details. Note: Replace <port> with the actual dev server port. The exact file contents are environment-specific, but the attack demonstrates exposure of internal source code via the vulnerable path.

Commit Details

Author: Nicholas Shahan

Date: 2026-05-01 14:34 UTC

Message:

[flutter_tools] Bump dwds dependency to v27.1.1 (#185357) Remove custom shelf handler for injected_client.js and allow the dwds handler to provide the file contents. The file is no longer shipped as an asset that can be read from disk. --------- Co-authored-by: Ben Konyi <bkonyi@google.com>

Triage Assessment

Vulnerability Type: Information disclosure

Confidence: MEDIUM

Reasoning:

The commit removes a custom shelf handler that read and served a specific JS file from disk and instead relies on the dwds handler to provide file contents. By eliminating the bespoke file read from disk, it reduces the risk of serving arbitrary or sensitive files via a custom path traversal or misconfiguration, and aligns with a more secure, standard handler flow. The change is coupled with a dependency bump and a change in asset serving, which has security implications beyond pure refactoring, indicating a potential fix of a previous insecure path for injected_client.js contents.

Verification Assessment

Vulnerability Type: Information disclosure

Confidence: MEDIUM

Affected Versions: Pre-fix Flutter tools versions prior to v1.16.3 (i.e., < v1.16.3)

Code Diff

diff --git a/packages/flutter_tools/lib/src/isolated/web_asset_server.dart b/packages/flutter_tools/lib/src/isolated/web_asset_server.dart index a2cc2b356ca8d..8ba8c0f06a65a 100644 --- a/packages/flutter_tools/lib/src/isolated/web_asset_server.dart +++ b/packages/flutter_tools/lib/src/isolated/web_asset_server.dart @@ -327,20 +327,6 @@ class WebAssetServer implements AssetReader { // Ensure dwds is present and provide middleware to avoid trying to // load the through the isolate APIs. - final Directory directory = await loadDwdsDirectory(fileSystem, logger); - shelf.Handler middleware(FutureOr<shelf.Response> Function(shelf.Request) innerHandler) { - return (shelf.Request request) async { - if (request.url.path.endsWith('dwds/src/injected/client.js')) { - final Uri uri = directory.uri.resolve('src/injected/client.js'); - final String result = await fileSystem.file(uri.toFilePath()).readAsString(); - return shelf.Response.ok( - result, - headers: <String, String>{HttpHeaders.contentTypeHeader: 'application/javascript'}, - ); - } - return innerHandler(request); - }; - } logging.Logger.root.level = logging.Level.ALL; logging.Logger.root.onRecord.listen((logging.LogRecord event) => log(logger, event)); @@ -398,7 +384,7 @@ class WebAssetServer implements AssetReader { ); var pipeline = const shelf.Pipeline(); if (shouldEnableMiddleware) { - pipeline = pipeline.addMiddleware(middleware).addMiddleware(dwds.middleware); + pipeline = pipeline.addMiddleware(dwds.middleware); } pipeline = pipeline.addMiddleware(proxyMiddleware(proxy, globals.logger)); final shelf.Handler dwdsHandler = pipeline.addHandler(server.handleRequest); diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index e4c16da62e4ed..88662f3158024 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: archive: 3.6.1 args: 2.7.0 dds: 5.3.0 - dwds: 26.2.5 + dwds: 27.1.1 code_builder: 4.11.1 collection: 1.19.1 completion: 1.0.2 @@ -128,4 +128,4 @@ dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 3bm17u +# PUBSPEC CHECKSUM: 7qgq4g diff --git a/pubspec.lock b/pubspec.lock index 19c3e349e9071..e2cb676d25075 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -311,10 +311,10 @@ packages: dependency: transitive description: name: dwds - sha256: "37829d11cc9ef3fe4cd8c6263873b4e8b640a8862d4d741b8fa58dd1eeadfb48" + sha256: d2fe0b3608330627871d7b0e070ffb4f356087a3e19fea64fa58f95a2c2871d6 url: "https://pub.dev" source: hosted - version: "26.2.5" + version: "27.1.1" extension_discovery: dependency: transitive description: @@ -1376,5 +1376,5 @@ packages: source: hosted version: "2.2.4" sdks: - dart: ">=3.11.0 <4.0.0" + dart: ">=3.12.0-307.0.dev <4.0.0" flutter: ">=3.38.4"
← Back to Alerts View on GitHub →