Repository navigation
fix(genui): only open http, https, mailto and tel URLs in openUrl - #1055
zachary-satterly wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request restricts the 'openUrl' function to only open absolute 'http', 'https', 'mailto', and 'tel' URLs, logging a warning and returning 'false' for any other schemes or relative URLs. It also adds corresponding unit tests. A review comment suggests adding error handling to the asynchronous 'canLaunchUrl' and 'launchUrl' calls to prevent unhandled exceptions from crashing the application.
| canLaunchUrl(uri).then((can) { | ||
| if (can) launchUrl(uri); | ||
| }); |
There was a problem hiding this comment.
The asynchronous calls to canLaunchUrl and launchUrl are executed without any error handling. If either of these calls throws an exception (e.g., due to platform limitations or configuration issues), it will result in an unhandled asynchronous error, which can crash the application or trigger global error handlers.
By returning the Future from launchUrl inside the then callback, we can chain the futures and catch any errors from both canLaunchUrl and launchUrl in a single .catchError block.
canLaunchUrl(uri).then((can) {
if (can) return launchUrl(uri);
return false;
}).catchError((Object e, StackTrace s) {
genUiLogger.warning('Failed to launch URL: $uri', e, s);
return false;
});50da678 to
8708e2c
Compare
OpenUrlFunction passed any URL the agent supplied to url_launcher. The only check was canLaunchUrl, which asks whether the platform has a handler for the URL. On desktop that is any registered scheme, including file: URLs. The A2UI basic catalog implementation guide has required a scheme allowlist for openUrl since a2ui-project/a2ui#1707, and a2ui-project/a2ui#2992 adds a check for http, https, mailto and tel to the Dart a2ui_core basic catalog. Apply the same set here. Other URLs, including relative ones, are refused with a logged warning and the function returns false without calling the launcher, the way genui's other basic functions report bad input. Tests use a fake UrlLauncherPlatform to check which URLs reach the launcher.
8708e2c to
acfd5fb
Compare
Description
OpenUrlFunction, the basic catalog'sopenUrl, passes whatever URL the agent sends tourl_launcher(basic_functions.dart). The only gate iscanLaunchUrl, which asks whether the platform has a handler for the URL. How much that filters depends on the platform:url_launcher_webonly reportshttp,https,mailto,telandsmsas launchable, so this change only adds a refusal ofsms:.canLaunchUrlis limited to the schemes the app declares in<queries>/LSApplicationQueriesSchemes, so the exposure is whatever the app has declared.canLaunchUrlis true for any scheme with a registered handler, includingfile:. So on desktop, an agent-built button can open local files or any custom-scheme handler installed on the machine.The A2UI basic catalog implementation guide lists a scheme allowlist for
openUrlunder "Security Constraints & Implementation Requirements (Mandatory)". It was added in a2ui-project/a2ui#1707, the fix for GHSA-72qq-p3r5-f7wq. a2ui-project/a2ui#2992 (merged 2026-10-06) adds a check forhttp,https,mailtoandtelto the Darta2ui_corebasic catalog. This PR applies the same set togenui, since apps on 0.10.x run this code until they move to the new packages.Changes:
openUrlopens only absolutehttp,https,mailtoandtelURLs. Anything else logs a warning throughgenUiLoggerand returnsfalsewithout calling the launcher. Apps that need other schemes can register their ownopenUrlclient function.basic_functions_test.dartswap in a fakeUrlLauncherPlatformand check which URLs reach it. This addsurl_launcher_platform_interfaceas a dev dependency.Where this differs from the guide, and why:
false, so this does the same. #2992 throws, which fitsa2ui_core's error model.canLaunchUrlalready rejected relative URLs, so they are refused.httpandhttpsonly. I used the set from #2992, which also allowsmailtoandtel, so the two Dart implementations agree. If you'd rather follow the guide exactly, I'll dropmailtoandtel.No issue was filed first because the change is small. The e2e workflow needs a repository secret, so it can't run from a fork.
I wrote this with help from an AI assistant (Claude) and reviewed the change myself. I couldn't run the Flutter test suite locally, so CI here is the first full run of the new tests.
Pre-launch Checklist
///).