[flutter_tools] Restrict release web asset server to the build output and source files#187437
Conversation
…ut and source files The release web asset server (used for `flutter run` release/profile/wasm web builds served via web-server or the browser) searches three roots for each request: the web build output directory, the Flutter SDK root, and the current project directory. Every matched file is returned with `Access-Control-Allow-Origin: *`. The project root and Flutter SDK root are only needed to resolve the original Dart sources and `.map` files referenced by a build's source maps. Because the whole roots were searched for any request, unrelated files under them (for example `.env`, `android/key.properties`, or other project/SDK files) could be served as well. Restrict the project and SDK roots to source-map related extensions (`.dart` and `.map`); the web build output directory remains unrestricted because it only contains generated, publishable assets. This keeps source-map resolution and normal web assets working while no longer serving unrelated files from those roots. Adds a test asserting that source files are still served from the project and SDK roots while non-source files under them are not.
There was a problem hiding this comment.
Code Review
This pull request restricts the files served by the ReleaseAssetServer from the project and Flutter SDK roots to only .dart and .map extensions, preventing exposure of unrelated files. A test is added to verify this behavior. Feedback suggests improving the test assertions by verifying that the exact content of the served files is returned, rather than just checking that the response is not the fallback HTML.
| for (final path in <String>['lib/main.dart', 'flutter/packages/flutter/lib/widget.dart']) { | ||
| final Response response = await assetServer.handle( | ||
| Request('GET', Uri.parse('http://localhost:8080/$path')), | ||
| ); | ||
| expect(response.statusCode, HttpStatus.ok, reason: '"$path" should be served'); | ||
| expect( | ||
| await response.readAsString(), | ||
| isNot('<html></html>'), | ||
| reason: '"$path" should be served, not the index.html fallback', | ||
| ); | ||
| } |
There was a problem hiding this comment.
Instead of asserting that the response is merely not the fallback '<html></html>', it is more robust and precise to assert that the response matches the exact content of the served file. This prevents false positives where the server might return an empty response or a different error message while still passing the isNot check.
final Map<String, String> expectedContents = <String, String>{\n 'lib/main.dart': 'void main() { }',\n 'flutter/packages/flutter/lib/widget.dart': '// sdk source',\n };\n for (final MapEntry<String, String> entry in expectedContents.entries) {\n final String path = entry.key;\n final String content = entry.value;\n final Response response = await assetServer.handle(\n Request('GET', Uri.parse('http://localhost:8080/$path')),\n );\n expect(response.statusCode, HttpStatus.ok, reason: '"$path" should be served');\n expect(\n await response.readAsString(),\n content,\n reason: '"$path" should return its correct content',\n );\n }
mdebbar
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
|
autosubmit label was removed for flutter/flutter/187437, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR. |
|
Updated the branch onto latest |
Summary
The release web asset server (
ReleaseAssetServer, used for release/profile/wasmweb builds served via
flutter run -d web-server/chrome) searches three rootswhen resolving each request:
and returns every matched file with
Access-Control-Allow-Origin: *.The project root (
currentDirectory) and the Flutter SDK root (_flutterRoot)are only needed so that the original Dart sources and
.mapfiles referenced bya build's source maps can be resolved. Because the whole roots were searched
for any request, unrelated files under them — for example
.env,android/key.properties, or other project/SDK files — were served as well, inaddition to the intended web build output.
This is a follow-up to #180699 ("[web] Don't serve files outside of project"),
which removed the home directory and the SDK parent directory from the search
paths but intentionally kept the project root and SDK root for source-map
resolution. This change tightens those two remaining roots.
Change
Restrict the project root and Flutter SDK root to the file extensions that
source-map resolution actually needs (
.dartand.map). The web build outputdirectory stays unrestricted because it only contains generated, publishable
assets.
Result:
build/web) — served as before (any file type).lib/main.dart, SDK.dart,.map)— still served from the project and SDK roots.
.env, signing config, etc.)— no longer served; they fall through to the
index.htmlfallback.Test
Adds a test to
web_asset_server_test.dartasserting that source files arestill served from the project and SDK roots, while non-source files under them
are not.
dart analyzeis clean for both changed files.