add warnings on suspicious activity in RN bridge communication
This commit is contained in:
Roman Volosovskyi 2018-01-15 12:04:39 +02:00
parent c4151534fb
commit f65e200fca
No known key found for this signature in database
GPG Key ID: 37135489EAE4B2D7
14 changed files with 1146 additions and 53 deletions

1
.env
View File

@ -9,4 +9,5 @@ LOG_LEVEL_STATUS_GO=info
JSC_ENABLED=1
QUEUE_MESSAGE_ENABLED=1
MANY_WHISPER_TOPICS_ENABLED=0
RN_BRIDGE_THRESHOLD_WARNINGS=1

View File

@ -4,8 +4,9 @@ ETHEREUM_DEV_CLUSTER=1
MAINNET_NETWORKS_ENABLED=1
OFFLINE_INBOX_ENABLED=1
OFFLINE_INBOX_MANY_ENABLED=0
LOG_LEVEL=debug
LOG_LEVEL=info
LOG_LEVEL_STATUS_GO=info
JSC_ENABLED=1
QUEUE_MESSAGE_ENABLED=1
MANY_WHISPER_TOPICS_ENABLED=0
MANY_WHISPER_TOPICS_ENABLED=0
RN_BRIDGE_THRESHOLD_WARNINGS=0

View File

@ -9,3 +9,4 @@ LOG_LEVEL_STATUS_GO=info
JSC_ENABLED=0
QUEUE_MESSAGE_ENABLED=0
MANY_WHISPER_TOPICS_ENABLED=0
RN_BRIDGE_THRESHOLD_WARNINGS=0

View File

@ -50,7 +50,12 @@
"emojilib",
"react-native-mapbox-gl",
"react-native-config",
"react-native-svg"
"react-native-svg",
"rn-snoopy",
"rn-snoopy/stream/bars",
"rn-snoopy/stream/filter",
"rn-snoopy/stream/buffer",
"react-native/Libraries/vendor/emitter/EventEmitter"
],
"imageDirs": [
"resources/images"

View File

@ -110,6 +110,7 @@
Cell * cell = [Cell new];
JSContext *context = [JSContext new];
[context setName:chatId];
cell.context = context;
HandlersJs *handlers = [HandlersJs new];

1054
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -87,7 +87,8 @@
"tty-browserify": "0.0.0",
"url": "0.10.3",
"vm-browserify": "0.0.4",
"web3": "github:status-im/web3.js#status-develop"
"web3": "github:status-im/web3.js#status-develop",
"rn-snoopy": "github:status-im/rn-snoopy"
},
"browser": {
"crypto": "react-native-crypto",

View File

@ -32,3 +32,8 @@
(def webview-bridge (js/require "react-native-webview-bridge"))
(def svg (js/require "react-native-svg"))
(def react-native-fcm (js/require "react-native-fcm"))
(def snoopy (js/require "rn-snoopy"))
(def snoopy-filter (js/require "rn-snoopy/stream/filter"))
(def snoopy-bars (js/require "rn-snoopy/stream/bars"))
(def snoopy-buffer (js/require "rn-snoopy/stream/buffer"))
(def EventEmmiter (js/require "react-native/Libraries/vendor/emitter/EventEmitter"))

View File

@ -13,7 +13,8 @@
[status-im.utils.utils :as utils]
[status-im.utils.config :as config]
[status-im.utils.notifications :as notifications]
[status-im.core :as core]))
[status-im.core :as core]
[status-im.utils.snoopy :as snoopy]))
(defn init-back-button-handler! []
(let [new-listener (fn []
@ -81,4 +82,5 @@
(defn init []
(status/set-soft-input-mode status/adjust-resize)
(init-back-button-handler!)
(core/init app-root))
(core/init app-root)
(snoopy/subscribe!))

View File

@ -75,7 +75,7 @@
(defview message-content-command-request
[{:keys [message-id content] :as message}]
(letsubs [command [:get-command (:content-command-ref content)]
(letsubs [command [:get-command (:content-command-ref content)]
answered? [:is-request-answered? message-id]
status-initialized? [:get :status-module-initialized?]]
{:component-will-mount #(when-not (:preview content)

View File

@ -13,7 +13,8 @@
[status-im.utils.utils :as utils]
[status-im.utils.config :as config]
[status-im.utils.notifications :as notifications]
[status-im.core :as core]))
[status-im.core :as core]
[status-im.utils.snoopy :as snoopy]))
(defn orientation->keyword [o]
(keyword (.toLowerCase o)))
@ -53,4 +54,5 @@
:reagent-render views/main})))
(defn init []
(core/init app-root))
(core/init app-root)
(snoopy/subscribe!))

View File

@ -31,3 +31,4 @@
(def jsc-enabled? (enabled? (get-config :JSC_ENABLED 0)))
(def queue-message-enabled? (enabled? (get-config :QUEUE_MESSAGE_ENABLED 0)))
(def many-whisper-topics-enabled? (enabled? (get-config :MANY_WHISPER_TOPICS_ENABLED 0)))
(def rn-bridge-threshold-warnings-enabled? (enabled? (get-config :RN_BRIDGE_THRESHOLD_WARNINGS 0)))

View File

@ -0,0 +1,101 @@
(ns status-im.utils.snoopy
(:require [status-im.react-native.js-dependencies :as js-dependencies]
[status-im.utils.config :as config]))
(def snoopy (.-default js-dependencies/snoopy))
(def sn-filter (.-default js-dependencies/snoopy-filter))
(def bars (.-default js-dependencies/snoopy-bars))
(def buffer (.-default js-dependencies/snoopy-buffer))
(defn create-filter [f]
(fn [message]
(let [method (.-method message)
module (.-module message)
args (.-args message)
first-arg (when (pos? (.-length args))
(aget args 0))]
(f {:method method
:module module
:first-arg first-arg}))))
(defn status-module-filter [{:keys [method module first-arg]}]
(or (= module "Status")
(and (= module "RCTNativeAppEventEmitter")
(= method "emit")
(= first-arg "gethEvent"))
(and
(string? method)
(clojure.string/starts-with? method "<callback for Status."))))
(defn timer-filter [{:keys [method]}]
(contains? #{"callTimers" "createTimer"} method))
(defn websocket-filter [{:keys [module first-arg]}]
(or (= module "WebSocketModule")
(and (= module "RCTDeviceEventEmitter")
(contains? #{"websocketFailed" "websocketMessage"} first-arg))))
(defn ui-manager-filter [{:keys [module]}]
(= module "UIManager"))
(defn touches-filter [{:keys [method module]}]
(and (= module "RCTEventEmitter")
(= method "receiveTouches")))
(defn native-animation-filter [{:keys [method module]}]
(or (= module "NativeAnimatedModule")
(and
(string? method)
(clojure.string/starts-with? method "<callback for NativeAnimatedModule."))))
(defn keyboard-observer-filter [{:keys [module]}]
;; mostly all calls to KeyboardObserver are done by FlatList
(= module "KeyboardObserver"))
(defn threshold-warnings
[{:keys [filter-fn label tick? print-events? threshold events threshold-message]}]
(.subscribe ((bars
(fn [a] (.-length a))
threshold
tick?
true
label
threshold-message)
((buffer) ((sn-filter (create-filter filter-fn)
print-events?)
events)))))
(defn subscribe! []
(when config/rn-bridge-threshold-warnings-enabled?
(let [emitter (js-dependencies/EventEmmiter.)
events (.stream snoopy emitter)]
(threshold-warnings
{:filter-fn (constantly true)
:label "all messages"
:threshold-message "too many calls to bridge, something suspicious is happening"
:tick? false
:print-events? false
:threshold 400
:events events})
(threshold-warnings
{:filter-fn timer-filter
:label "timer"
:threshold-message "too many setTimeout/setInterval calls"
:tick? false
:print-events? false
:threshold 70
:events events})
(threshold-warnings
{:filter-fn ui-manager-filter
:label "timer"
:threshold-message (str "too many calls to UIManager, most likely during navigation. "
"Please consider preloading of screens or lazy loading of some components")
:tick? false
:print-events? false
;; todo(rasom): revisit this number when/if
;; https://github.com/status-im/status-react/pull/2849 will be merged
:threshold 200
:events events}))))

View File

@ -36,4 +36,10 @@
(def svg #js {:default #js {}})
(def react-native-fcm #js {:default #js {}})
(def snoopy #js {:default #js {}})
(def snoopy-filter #js {:default #js {}})
(def snoopy-bars #js {:default #js {}})
(def snoopy-buffer #js {:default #js {}})
(def EventEmmiter #js {})