Skip to content

Make sure that extensions are bundled with the package they claim to be. - #9981

Open
johnpryan wants to merge 7 commits into
flutter:masterfrom
johnpryan:package-centric-extensions
Open

Make sure that extensions are bundled with the package they claim to be.#9981
johnpryan wants to merge 7 commits into
flutter:masterfrom
johnpryan:package-centric-extensions

Conversation

@johnpryan

Copy link
Copy Markdown
Contributor

With this change, extensions are enabled if and only if the package name on disk matches the package name in extension/devtools/config.yaml.

This supersedes #9965

With this change, extensions are enabled if and only if the package name
on disk matches the package name in extension/devtools/config.yaml.
@johnpryan
johnpryan requested review from a team, bkonyi and kenzieschmoll as code owners August 26, 2026 21:40
@johnpryan
johnpryan requested review from srawlins and removed request for a team August 26, 2026 21:40

@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 improves DevTools extension isolation by tracking the providing package name for enablement, deduplication, and asset loading, and adds validation checks for extension names. The review feedback highlights a compilation error in _extensions_api.dart due to invalid map literal syntax, a potential runtime TypeError in _validate.dart when casting the configuration name, and a suggestion to normalize packageRoot in extension_manager.dart for more robust path comparisons.

Comment thread packages/devtools_app/lib/src/shared/server/_extensions_api.dart
Comment thread packages/devtools_extensions/bin/_validate.dart Outdated
Comment thread packages/devtools_shared/lib/src/extensions/extension_manager.dart Outdated
Comment thread packages/devtools_app/lib/src/extensions/extension_service_helpers.dart Outdated
return DevToolsExtensionConfig._(
// These values are required fields in the extension's config.yaml file.
name: name,
packageName: packageName,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the comment above name is intended for all keys until the next comment on line 82, so package should not go here unless we are expecting users to manually enter this in the extension config.yaml file.

Comment thread packages/devtools_shared/CHANGELOG.md

// Spoofed package does not inherit provider's enablement
expect(
options.lookupExtensionEnabledState(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this going to be backwards compatible for existing devtools_options.yaml entries from before this change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, for most packages (like patrol or provider), the packageName field (from .dart_tool/package_config.json') matches the name` field (the package name the extension is declared to before in config.yaml).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If they don't match, then users will need to re-enable the extension after this change lands, because DevToolsExtensionConfig.identifier will be put in devtools_options.yaml file instead.

// Write the new enabled state to the map.
final extension = extensions.firstWhereOrNull(
(e) => e.keys.first == extensionName,
(e) => e.keys.first == targetKey,

@kenzieschmoll kenzieschmoll Aug 31, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

won't we end up in a situation where users who already have an extension enabled in their devtools options file, call if foo_ext provided by package foo will now have two keys in their devtools_options.yaml file:
foo.foo_ext and foo_ext since targetKey is now foo.foo_ext?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's possible.

throw FileSystemException('${packageDirectory.path} directory not found');
}

final pubspecFile = File(path.join(packageDirectory.path, 'pubspec.yaml'));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the additional validations added to this file seem useful, but they also seem out of scope of this PR. Are these somehow related to resolving the security bug?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think AGY added this because extensions need to be included in a Dart package, right?

codePoint = codePointFromJson as int;
}

final packageName = json[packageNameKey] as String? ?? name;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

where is the packageName getting set in the json? Maybe I'm missing it in this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In extension_manager.dart L191, the ExtensionsManager class puts this key into DevToolsExtensionConfig manually when detecting the available extensions.

Comment on lines +157 to +159
/// This value is parsed from the package name in
/// `.dart_tool/package_config.json`.
final String packageName;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

related to my last comment. Where is this parsing code?

@johnpryan johnpryan Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My understanding is that this is parsed from the package_config.json file in the extension_discovery package, and then ExtensionsManager puts this value into DevToolsExtensionConfig.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants