Sitelet https://github.com/flutter/flutter/pull/191294
Skip to content

[stable] [flutter_tools] Validate plugin class/package identifiers to prevent GeneratedPluginRegistrant injection - #191294

Merged
auto-submit[bot] merged 1 commit into
flutter:flutter-3.47-candidate.0from
bkonyi:cherry-pick-189156-to-stable
Aug 18, 2026
Merged

auto-submit[bot] merged 1 commit into
flutter:flutter-3.47-candidate.0from
bkonyi:cherry-pick-189156-to-stable

Conversation

@bkonyi

@bkonyi bkonyi commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

This pull request is created by automatic cherry pick workflow
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.

Issue Link:

#189156

Impact Description:

Plugin pluginClass, dartPluginClass, and Android package fields are interpolated verbatim into generated GeneratedPluginRegistrant native source files (Swift, Objective-C, Java, Kotlin, C++). Previously, validation only checked that these fields were strings, allowing transitive dependencies with malicious or malformed plugin identifiers to inject arbitrary code into GeneratedPluginRegistrant during flutter pub get or flutter build.

Changelog Description:

[flutter/189156] Validate plugin class and package identifiers to prevent arbitrary code injection into GeneratedPluginRegistrant.

Workaround:

Inspect transitive dependency pubspec.yaml plugin configurations manually.

Risk:

  • Low
  • Medium
  • High

Test Coverage:

  • Yes
  • No

Validation Steps:

  1. Test a plugin declaration containing non-identifier characters in pluginClass or package.
  2. Confirm that the tool rejects the invalid plugin specification.
  3. Run packages/flutter_tools/test/general.shard/plugins_test.dart.

…GeneratedPluginRegistrant injection (flutter#189156)

## Description

Plugin `pluginClass`/`dartPluginClass` and the Android `package` are
interpolated **verbatim** into the generated `GeneratedPluginRegistrant`
source files. `flutter_plugins.dart` renders these templates via
`_renderTemplateToFile` → `templateRenderer.renderString(template,
context)`, and the renderer's `htmlEscapeValues` defaults to `false`, so
the values are emitted with no escaping into Java/Kotlin, Swift,
Objective-C and C++ source (e.g. `new {{package}}.{{class}}()`,
`{{prefix}}{{class}}.register(...)`, `#import <{{name}}/{{class}}.h>`).

The per-platform `validate()` methods in `platform_plugins.dart` only
checked that these fields were *strings*, not that they were valid
identifiers. As a result a plugin declaration whose
`pluginClass`/`package` contains arbitrary source (spaces, `;`, `{}`,
`()`, newlines, …) passes validation and that source lands in the
consuming app's `GeneratedPluginRegistrant` and is compiled into the
app.

Because plugins are collected over `computeTransitiveDependencies(...)`
with no opt-in from the consuming app, a **transitive** dependency can
use this to have arbitrary native code compiled into an app that merely
depends on it (via a plain `flutter pub get` / `build` / `run`). This is
the same "a package must not escape its declared boundary at build time"
boundary enforced for asset paths in flutter#187661 and for pub-cache
extraction in CVE-2026-27704.

Reproduced end-to-end: a dependency declaring
```yaml
flutter:
  plugin:
    platforms:
      macos:
        pluginClass: "SomePlugin.register(...); <injected statements>; if false { SomePlugin"
```
resulted, after `flutter pub get`, in the injected statements appearing
verbatim in `macos/Flutter/GeneratedPluginRegistrant.swift` and
`ios/Runner/GeneratedPluginRegistrant.m`.

## Fix

Restrict `pluginClass`, `dartPluginClass` and the Android `package` to
identifier characters (dot-separated identifiers) in each platform's
`validate()`, rejecting the plugin specification otherwise. Legitimate
class/package names are unaffected; a value that is not a plain
identifier now fails with `Invalid plugin specification <name>`.

## Tests

- Added a regression test asserting a `pluginClass` containing injection
characters is rejected.
- Full `test/general.shard/plugins_test.dart` passes (77/77) — no
legitimate plugin specification regresses.

## Pre-launch Checklist

- [x] I added new tests to check the change I am making.
- [x] All existing and new tests are passing.

---------

Co-authored-by: Ben Konyi <bkonyi@google.com>
@bkonyi bkonyi added the cp: review Cherry-picks in the review queue label Aug 18, 2026
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Aug 18, 2026
@flutter-dashboard

Copy link
Copy Markdown

This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter.

Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed.

@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Aug 18, 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 introduces validation for plugin identifiers and Dart file names across all supported platforms to prevent arbitrary code injection via pubspec declarations. Unit tests were added to verify that malicious inputs are rejected. The feedback suggests expanding test coverage to also validate fileName for web plugins and dartFileName for other platforms.

throwsToolExit(message: 'Invalid plugin specification evil_dart_plugin'),
);
},
);

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

While the new tests cover pluginClass and dartPluginClass validation, they do not cover fileName validation for web plugins or dartFileName validation for other platforms. Adding tests for these ensures that path traversal and injection attempts via file names are also correctly rejected and do not regress.

      );

      testUsingContext(
        'Plugin.fromYaml rejects a web plugin whose fileName contains injection',
        () async {
          const maliciousYaml = '''
platforms:
  web:
    pluginClass: SafeClass
    fileName: "some_file.dart'; evilInjectedCall(); //"
''';
          expect(
            () => Plugin.fromYaml(
              'evil_web_plugin',
              '',
              loadYaml(maliciousYaml) as YamlMap,
              null,
              const <String>[],
              fileSystem: globals.fs,
              isDevDependency: false,
            ),
            throwsToolExit(),
          );
        },
      );

      testUsingContext(
        'Plugin.fromYaml rejects a platform plugin whose dartFileName contains injection',
        () async {
          const maliciousYaml = '''
platforms:
  android:
    dartPluginClass: SafeClass
    dartFileName: "some_file.dart'; evilInjectedCall(); //"
''';
          expect(
            () => Plugin.fromYaml(
              'evil_android_plugin',
              '',
              loadYaml(maliciousYaml) as YamlMap,
              null,
              const <String>[],
              fileSystem: globals.fs,
              isDevDependency: false,
            ),
            throwsToolExit(
              message: 'The plugin `evil_android_plugin` has an invalid `dartFileName` for platform `android` in pubspec.yaml.',
            ),
          );
        },
      );
References
  1. Code should be tested and follow the guidance described in the writing effective tests guide. (link)

@eyebrowsoffire eyebrowsoffire added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 18, 2026
@auto-submit
auto-submit Bot merged commit 9ee1431 into flutter:flutter-3.47-candidate.0 Aug 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD cp: review Cherry-picks in the review queue tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants