-
Notifications
You must be signed in to change notification settings - Fork 31
DART-246 Modify rule S7409: Add Dart language #5029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
antonioaversa
merged 6 commits into
master
from
antonio/DART-246-S7409-add-dart-language
May 22, 2025
Merged
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
8f8e461
DART-246 Modify rule S7409: Add Dart language
antonioaversa 9d5f508
Fix package name
antonioaversa 9c5bde6
Review and update S7409 for Dart
pierre-loup-tristant-sonarsource 520522e
Add Drt syntax highlighting for code examples
pierre-loup-tristant-sonarsource 461e65c
Update S7409 title for all languages
pierre-loup-tristant-sonarsource a536907
Apply suggestions from code review
pierre-loup-tristant-sonarsource File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{ | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
include::../description.adoc[] | ||
|
||
include::../ask-yourself.adoc[] | ||
|
||
== Recommended Secure Coding Practices | ||
|
||
=== Disable JavaScript | ||
|
||
If it is possible to disable JavaScript in the WebView, this is the most secure option. | ||
|
||
When using the https://pub.dev/packages/webview_flutter[`webview_flutter` package] v4 and above, by default | ||
JavaScript is disabled in every https://pub.dev/documentation/webview_flutter/latest/webview_flutter/WebViewController-class.html[`WebViewController`] | ||
instance. Therefore, https://pub.dev/documentation/webview_flutter/latest/webview_flutter/WebViewController/setJavaScriptMode.html[`setJavaScriptMode`] | ||
does not need to be explicitly called with https://pub.dev/documentation/webview_flutter/latest/webview_flutter/JavaScriptMode.html[`JavaScriptMode.disabled`]. | ||
|
||
The same applies to https://pub.dev/documentation/webview_flutter/3.0.4/webview_flutter/WebView-class.html[`WebView`] | ||
instances in https://pub.dev/packages/webview_flutter[`webview_flutter` package] v3 and below: there is no | ||
need to explicitly set the named constructor parameter `javascriptMode` to https://pub.dev/documentation/webview_flutter/3.0.4/webview_flutter/JavascriptMode.html[`JavascriptMode.disabled`]. | ||
|
||
When using the https://pub.dev/packages/flutter_inappwebview[`flutter_inappwebview` package], on the other hand, | ||
the default behavior is to enable JavaScript. Therefore, it is necessary to set the `enableJavaScript` parameter | ||
to `false` in https://pub.dev/documentation/flutter_inappwebview/latest/flutter_inappwebview/InAppWebViewSettings-class.html[InAppWebViewSettings] | ||
and https://pub.dev/documentation/flutter_inappwebview/latest/flutter_inappwebview/InAppWebViewOptions-class.html[InAppWebViewOptions] | ||
instances. | ||
pierre-loup-tristant-sonarsource marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Of course, sometimes it is necessary to enable, or keep enabled, JavaScript, in which case the following | ||
pierre-loup-tristant-sonarsource marked this conversation as resolved.
Show resolved
Hide resolved
|
||
recommendations should be considered. | ||
|
||
=== Remove JavaScript interface when loading untrusted content | ||
|
||
JavaScript interfaces can be removed at a later point. It is recommended to remove the JavaScript | ||
interface when it is no longer needed. If it is needed for a longer time, consider removing it before | ||
loading untrusted content. This can be done by calling `webViewController.removeJavaScriptChannel('channelName')` for the https://pub.dev/packages/webview_flutter[`webview_flutter` package] or `webViewController.removeJavaScriptHandler('channelName')` for the https://pub.dev/packages/flutter_inappwebview[`flutter_inappwebview` package]. | ||
|
||
A good place to do this in Flutter is inside navigation callbacks like https://pub.dev/documentation/webview_flutter/latest/webview_flutter/NavigationDelegate/onNavigationRequest.html[`NavigationDelegate.onNavigationRequest`] | ||
for the https://pub.dev/packages/webview_flutter[`webview_flutter` package] or https://pub.dev/documentation/flutter_inappwebview/latest/flutter_inappwebview/PlatformInAppBrowserEvents/shouldOverrideUrlLoading.html[`WebViewClient.shouldOverrideUrlLoading`] | ||
for the https://pub.dev/packages/flutter_inappwebview[`flutter_inappwebview` package] package, where you can check the URL being loaded and remove the JavaScript channel | ||
if the content is untrusted. | ||
|
||
=== Alternative methods to implement native bridges | ||
|
||
If a native channel has to be added to the web view or its controller, and it is impossible to remove it | ||
pierre-loup-tristant-sonarsource marked this conversation as resolved.
Show resolved
Hide resolved
|
||
at a later point, consider using an alternative method that offers more control over the communication flow. | ||
|
||
For the `webview_flutter` package, there is currently no way to know the origin of an incoming JavaScript message. Therefore using JavaScript communication with `webview_flutter` is discouraged. | ||
|
||
For the `flutter_inappwebview` package, use https://pub.dev/documentation/flutter_inappwebview/latest/flutter_inappwebview/WebMessageListener-class.html[`WebMessageListener`] which allows you to restrict the origins that can send messages to your application. | ||
|
||
== Sensitive Code Example | ||
|
||
https://pub.dev/packages/webview_flutter[`webview_flutter`] | ||
[source,dart] | ||
---- | ||
final _controller = WebViewController() | ||
..setJavaScriptMode(JavaScriptMode.unrestricted) | ||
..addJavaScriptChannel("channel", onMessageReceived: (m) {}); // Sensitive | ||
---- | ||
|
||
https://pub.dev/packages/flutter_inappwebview[`flutter_inappwebview`] | ||
[source,dart] | ||
---- | ||
InAppWebView( | ||
onWebViewCreated: (controller) { | ||
controller?.addJavaScriptHandler( // Sensitive | ||
handlerName: "channel", | ||
callback: (args) {} | ||
); | ||
}, | ||
); | ||
---- | ||
|
||
== Compliant Solution | ||
|
||
The most secure option is to not enable, or disable, JavaScript entirely. S6362 further explains why it should not | ||
be enabled unless absolutely necessary. | ||
|
||
https://pub.dev/packages/webview_flutter[`webview_flutter`] | ||
[source,dart] | ||
---- | ||
final _controller = WebViewController(); | ||
---- | ||
|
||
If possible, remove the JavaScript channel after it is no longer needed, or before loading any untrusted content. | ||
|
||
https://pub.dev/packages/webview_flutter[`webview_flutter`] | ||
[source,dart] | ||
---- | ||
_controller.removeJavaScriptChannel("channel"); | ||
---- | ||
|
||
https://pub.dev/packages/flutter_inappwebview[`flutter_inappwebview`] | ||
[source,dart] | ||
---- | ||
_controller.removeJavaScriptHandler("channel"); | ||
---- | ||
|
||
If a JavaScript channel must be used, consider using `flutter_inappwebview` instead of `webview_flutter`. The Web Message API allows you to restrict the origins that can send messages to the JavaScript bridge. | ||
|
||
[source,dart] | ||
---- | ||
egon-okerman-sonarsource marked this conversation as resolved.
Show resolved
Hide resolved
|
||
InAppWebView( | ||
onWebViewCreated: (controller) async { | ||
await inAppController.addWebMessageListener( | ||
WebMessageListener( | ||
jsObjectName: "channel", | ||
allowedOriginRules: { | ||
"https://secure-origin", | ||
}, // Restrict to specific origin | ||
onPostMessage: (message, origin, isMainFrame, replyProxy) {}, | ||
), | ||
); | ||
}, | ||
); | ||
---- | ||
|
||
include::../see.adoc[] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.