Skip to content

[flutter_tools] Restrict release web asset server to the build output and source files#187437

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
adilburaksen:harden-release-asset-server-search-path
Jun 24, 2026
Merged

[flutter_tools] Restrict release web asset server to the build output and source files#187437
auto-submit[bot] merged 2 commits into
flutter:masterfrom
adilburaksen:harden-release-asset-server-search-path

Conversation

@adilburaksen

Copy link
Copy Markdown
Contributor

Summary

The release web asset server (ReleaseAssetServer, used for release/profile/wasm
web builds served via flutter run -d web-server/chrome) searches three roots
when resolving each request:

List<Uri> _searchPaths() => <Uri>[
  _fileSystem.directory(_webBuildDirectory).uri,
  _fileSystem.directory(_flutterRoot).uri,
  _fileSystem.currentDirectory.uri,
];

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 .map files referenced by
a 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, in
addition 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 (.dart and .map). The web build output
directory stays unrestricted because it only contains generated, publishable
assets.

Result:

  • Web build output (build/web) — served as before (any file type).
  • Source files referenced by source maps (lib/main.dart, SDK .dart, .map)
    — still served from the project and SDK roots.
  • Unrelated files under the project/SDK roots (.env, signing config, etc.)
    — no longer served; they fall through to the index.html fallback.

Test

Adds a test to web_asset_server_test.dart asserting that source files are
still served from the project and SDK roots, while non-source files under them
are not. dart analyze is clean for both changed files.

…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.
@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jun 2, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +264 to +274
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',
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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      }

@bkonyi
bkonyi requested review from harryterkelsen and mdebbar June 16, 2026 21:19
@bkonyi bkonyi added the team-web Owned by Web platform team label Jun 16, 2026

@harryterkelsen harryterkelsen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mdebbar mdebbar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

@mdebbar mdebbar added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Jun 23, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 23, 2026
@auto-submit

auto-submit Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

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.

@github-actions github-actions Bot removed team-web Owned by Web platform team CICD Run CI/CD labels Jun 23, 2026
@adilburaksen

Copy link
Copy Markdown
Contributor Author

Updated the branch onto latest main to clear the "base older than 7 days" block — CI is re-running now. Since this is already approved, could a maintainer re-apply the autosubmit label when checks are green? I don't have label permissions on the repo. Thanks @mdebbar @harryterkelsen!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants