Description
Steps to reproduce
- Create a new app:
flutter create bug - Enable generation in pubspec.yaml (
flutter: generate: true) and add an
l10n.yaml+lib/l10n/app_en.arbas per the standard localization setup. - In
app_en.arb, set a placeholder'stypeattribute to a crafted string
that closes the generated method and injects a new member (see Code sample). - Run
flutter gen-l10n. - Inspect the generated
app_localizations_en.dart. - Run
dart analyzeon the generated output.
Reproduced on Flutter web and on a physical device (Pixel 6a, Android 16).
Expected results
flutter gen-l10n should validate the placeholder type attribute the same
way it already validates resource names (which are checked against
_isValidGetterAndMethodName). An illegal type value should raise an
L10nException and fail generation, rather than being written into source.
Ideally the supported types would be allowlisted (String, int, double, num,
DateTime, Object, plus the documented numeric/date format types).
Actual results
The placeholder type is read as a raw, unchecked string
(gen_l10n_types.dart:235) and interpolated into the generated method
signature (gen_l10n.dart:130, generateMethodParameters). A crafted type
string closes the generated method early, injects arbitrary members, and
reopens a declaration to absorb the remainder of the template.
The resulting file is valid Dart: it compiles, and dart analyze reports
"No issues found." The injected code executes whenever the corresponding
localization getter is called (e.g. AppLocalizations.of(context).greeting(...)).
The tool applies the exact identifier check it needs to the resource name
but not to the sibling type field that ends up in the same generated source.
Code sample
app_en.arb:
{
"@@locale": "en",
"greeting": "Hello {user}",
"@greeting": {
"placeholders": {
"user": {
"type": "Object user) { print('>>> ARBITRARY DART EXECUTED FROM A TRANSLATION FILE <<<'); return 'pwned'; } String injectedByTranslation(Object"
}
}
}
}Generated app_localizations_en.dart after flutter gen-l10n:
class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String greeting(Object user) {
print('>>> ARBITRARY DART EXECUTED FROM A TRANSLATION FILE <<<'); // injected
return 'pwned';
}
String injectedByTranslation(Object user) { // injected member
return 'Hello $user';
}
}dart analyze on the generated file returns "No issues found!".
Screenshots or Video
Logs
No response
Flutter Doctor output
N/A
Activity
Badranh commentedon Sep 1, 2026
app.zip
App sample
suryaKommana2662 commentedon Sep 2, 2026
@Badranh Thanks for the report. I was able to reproduce the reported issue using the provided sample.
flutter gen-l10nsuccessfully processed the crafted.arbfile and generated Dart source containing the injected code.dart analyzedid not report any errors related to the injected code and I also ran the application withflutter run -d chromeand confirmed that the injected localization output is used at runtime. The application displayed:PWNED by a translation file (original was: Hello {user})Routing to the
team-toolfor further investigation[flutter_tools] validate placeholder type in gen-l10n (flutter#192434)
github-actions commentedon Sep 24, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.