107 lines
3.1 KiB
Plaintext
107 lines
3.1 KiB
Plaintext
![]() |
include::../description.adoc[]
|
||
|
|
||
|
include::../ask-yourself.adoc[]
|
||
|
|
||
|
:setJavaScriptEnabledSnippet: webSettings.setJavaScriptEnabled(false)
|
||
|
|
||
|
include::../recommended.adoc[]
|
||
|
|
||
|
== Sensitive Code Example
|
||
|
|
||
|
[source,java]
|
||
|
----
|
||
|
public class ExampleActivity extends AppCompatActivity {
|
||
|
@Override
|
||
|
protected void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
|
||
|
WebView webView = new WebView(this);
|
||
|
webView.getSettings().setJavaScriptEnabled(true);
|
||
|
webView.addJavascriptInterface(new JavaScriptBridge(), "androidBridge"); // Sensitive
|
||
|
}
|
||
|
|
||
|
public static class JavaScriptBridge {
|
||
|
@JavascriptInterface
|
||
|
public String accessUserData(String userId) {
|
||
|
return getUserData(userId);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
----
|
||
|
|
||
|
== Compliant Solution
|
||
|
|
||
|
The most secure option is to disable JavaScript entirely. S6362 further explains why it should not be enabled
|
||
|
unless absolutely necessary.
|
||
|
|
||
|
[source,java]
|
||
|
----
|
||
|
public class ExampleActivity extends AppCompatActivity {
|
||
|
@Override
|
||
|
protected void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
|
||
|
WebView webView = new WebView(this);
|
||
|
webView.getSettings().setJavaScriptEnabled(false);
|
||
|
}
|
||
|
}
|
||
|
----
|
||
|
|
||
|
If possible, remove the JavaScript interface after it is no longer needed, or before loading any untrusted content.
|
||
|
|
||
|
[source,java]
|
||
|
----
|
||
|
public class ExampleActivity extends AppCompatActivity {
|
||
|
@Override
|
||
|
protected void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
|
||
|
WebView webView = new WebView(this);
|
||
|
webView.getSettings().setJavaScriptEnabled(true);
|
||
|
|
||
|
webView.addJavascriptInterface(new JavaScriptBridge(), "androidBridge");
|
||
|
|
||
|
// Sometime later, before unsafe content is loaded, remove the JavaScript interface
|
||
|
webView.removeJavascriptInterface("androidBridge");
|
||
|
}
|
||
|
}
|
||
|
----
|
||
|
|
||
|
If a JavaScript bridge must be used, consider using ``WebViewCompat.addWebMessageListener`` instead. This allows you to restrict
|
||
|
the origins that can send messages to the JavaScript bridge.
|
||
|
|
||
|
[source,java]
|
||
|
----
|
||
|
public class ExampleActivity extends AppCompatActivity {
|
||
|
private static final Set<String> ALLOWED_ORIGINS = Collections.singleton("https://example.com");
|
||
|
|
||
|
@Override
|
||
|
protected void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
|
||
|
WebView webView = new WebView(this);
|
||
|
webView.getSettings().setJavaScriptEnabled(true);
|
||
|
|
||
|
WebViewCompat.addWebMessageListener(
|
||
|
webView,
|
||
|
"androidBridge",
|
||
|
ALLOWED_ORIGINS, // Only allow messages from these origins
|
||
|
new WebMessageListener() {
|
||
|
@Override
|
||
|
public void onPostMessage(
|
||
|
WebView view,
|
||
|
WebMessageCompat message,
|
||
|
Uri sourceOrigin,
|
||
|
boolean isMainFrame,
|
||
|
JavaScriptReplyProxy replyProxy
|
||
|
) {
|
||
|
// Handle the message
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
----
|
||
|
|
||
|
include::../see.adoc[]
|