mihari 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  4. data/.standard.yml +4 -0
  5. data/README.md +3 -1
  6. data/docker/Dockerfile +2 -1
  7. data/images/web_alerts.png +0 -0
  8. data/lib/mihari/analyzers/base.rb +1 -1
  9. data/lib/mihari/analyzers/securitytrails.rb +2 -2
  10. data/lib/mihari/cli.rb +61 -287
  11. data/lib/mihari/commands/binaryedge.rb +21 -0
  12. data/lib/mihari/commands/censys.rb +22 -0
  13. data/lib/mihari/commands/circl.rb +21 -0
  14. data/lib/mihari/commands/config.rb +21 -0
  15. data/lib/mihari/commands/crtsh.rb +22 -0
  16. data/lib/mihari/commands/dnpedia.rb +21 -0
  17. data/lib/mihari/commands/dnstwister.rb +19 -0
  18. data/lib/mihari/commands/free_text.rb +21 -0
  19. data/lib/mihari/commands/http_hash.rb +25 -0
  20. data/lib/mihari/commands/json.rb +36 -0
  21. data/lib/mihari/commands/onyphe.rb +19 -0
  22. data/lib/mihari/commands/otx.rb +21 -0
  23. data/lib/mihari/commands/passive_dns.rb +19 -0
  24. data/lib/mihari/commands/passive_ssl.rb +21 -0
  25. data/lib/mihari/commands/passivetotal.rb +21 -0
  26. data/lib/mihari/commands/pulsedive.rb +21 -0
  27. data/lib/mihari/commands/reverse_whois.rb +21 -0
  28. data/lib/mihari/commands/securitytrails.rb +20 -0
  29. data/lib/mihari/commands/securitytrails_domain_feed.rb +23 -0
  30. data/lib/mihari/commands/shodan.rb +19 -0
  31. data/lib/mihari/commands/spyse.rb +20 -0
  32. data/lib/mihari/commands/ssh_fingerprint.rb +21 -0
  33. data/lib/mihari/commands/urlscan.rb +23 -0
  34. data/lib/mihari/commands/virustotal.rb +19 -0
  35. data/lib/mihari/commands/web.rb +20 -0
  36. data/lib/mihari/commands/zoomeye.rb +20 -0
  37. data/lib/mihari/config.rb +12 -0
  38. data/lib/mihari/configurable.rb +1 -1
  39. data/lib/mihari/emitters/slack.rb +4 -4
  40. data/lib/mihari/emitters/the_hive.rb +1 -1
  41. data/lib/mihari/models/alert.rb +5 -5
  42. data/lib/mihari/notifiers/exception_notifier.rb +4 -4
  43. data/lib/mihari/status.rb +1 -1
  44. data/lib/mihari/version.rb +1 -1
  45. data/lib/mihari/web/app.rb +45 -5
  46. data/lib/mihari/web/public/index.html +2 -2
  47. data/lib/mihari/web/public/static/js/{app.58b32d15.js → app.280cbdb7.js} +4 -4
  48. data/lib/mihari/web/public/static/js/app.280cbdb7.js.map +1 -0
  49. data/mihari.gemspec +2 -0
  50. metadata +61 -4
  51. data/lib/mihari/web/public/static/js/app.58b32d15.js.map +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cf190c27b1be3c0eeb690354361c3bb3295beb8609661a861fcc31e227cb7f0
4
- data.tar.gz: e989209e3668e9342803ed1b91c9e668bcf0519e659f9fb88687cc38460818cb
3
+ metadata.gz: dff04f8065ceff1c6b9fa68bd606db9cc4789ed034a330019143a69c4ec2c037
4
+ data.tar.gz: d307e3e48eedf5d17245da14a20bd578468e03a70b2ba302fcc4ea68aab5651c
5
5
  SHA512:
6
- metadata.gz: 0a40de96264eaf211240b0020aa3494e6a64bddf8e2aa74461e91122fff29d72a5ab66032e226fa80c19c984fcb7a3e37d1e78aa0da317f6fd1445945b93d200
7
- data.tar.gz: b0b55e75e84037cf7761fd28128504d45fc049de01d0f4db65184b2e8ff0e9bc3948e06b8165e90c19244fb1c8b8af33efa77d260bb323d4084d85e21f72245f
6
+ metadata.gz: 97f8237d491778739e307e15d0b5b96fba510a548a0a42ae1760e41469cef7fad551b6e876025d7daed58e449c77bee6d3573d659c85e4b2886712229e2ee7ef
7
+ data.tar.gz: 2d5f9125f2039ce7d8727661a8f71f1a7c0b9021a0eaf613242598371fb6066234fa5a8959528190bc7275b35da026932700d13929cfd9f94aa04eded6881951
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a bug report to help us improve
4
+ title: "[BUG]"
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ <!--
11
+ Thank you for taking the time to report a bug.
12
+ Please make sure there is no existing issue about this kind of bug.
13
+ -->
14
+
15
+ ### **Describe the bug**
16
+
17
+ A clear and concise description of what the bug is.
18
+
19
+ ### **Steps to reproduce**
20
+
21
+ - ...
22
+
23
+ ### **Expected behavior**
24
+
25
+ A clear and concise description of what you expected to happen.
26
+
27
+ ### **Actual behavior**
28
+
29
+ A clear and concise description of what actually happened.
30
+
31
+ ### **Screenshots**
32
+
33
+ Add screenshots to help explain your problem.
34
+
35
+ ### **System Information:**
36
+
37
+ - OS: [e.g. Windows10]
38
+ - Ruby version: [e.g. 3.0]
39
+ - Mihari version: [e.g. 2.0.0]
40
+
41
+ ### **Additional context**
42
+
43
+ Add any other context about the problem here.
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest a new Feature for Mihari
4
+ title: "[Feature Request]"
5
+ labels: enhancement
6
+ assignees: ''
7
+
8
+ ---
9
+ <!--
10
+
11
+ 1. Make sure your requested feature makes sense for Mihari.
12
+
13
+ 2. If you want to suggest a new integration of a service, please provide detailed information of it. (e.g. API docs)
14
+
15
+ -->
data/.standard.yml ADDED
@@ -0,0 +1,4 @@
1
+ ignore:
2
+ - "**/*":
3
+ - Layout/SpaceInsideHashLiteralBraces
4
+ - Style/RescueStandardError
data/README.md CHANGED
@@ -50,9 +50,11 @@ See [Usage](https://github.com/ninoseki/mihari/wiki/Usage) for more information.
50
50
 
51
51
  - [Requirements & Installation](https://github.com/ninoseki/mihari/wiki/Requirements-&-Installation)
52
52
  - [Usage](https://github.com/ninoseki/mihari/wiki/Usage)
53
+ - [Built-in Web App](https://github.com/ninoseki/mihari/wiki/Built-in-Web-App)
53
54
  - [Configuration](https://github.com/ninoseki/mihari/wiki/Configuration)
54
- - [Custom script](https://github.com/ninoseki/mihari/wiki/Custom-script)
55
+ - [Custom Script](https://github.com/ninoseki/mihari/wiki/Custom-Script)
55
56
  - [Docker](https://github.com/ninoseki/mihari/wiki/Docker)
57
+ - [GitHub Actions](https://github.com/ninoseki/mihari/wiki/GitHub-Actions)
56
58
 
57
59
  ## License
58
60
 
data/docker/Dockerfile CHANGED
@@ -1,6 +1,7 @@
1
1
  FROM ruby:3.0.0-alpine3.13
2
2
 
3
- RUN apk --no-cache add git build-base ruby-dev sqlite-dev postgresql-dev \
3
+ RUN apk --no-cache add git build-base ruby-dev sqlite-dev postgresql-dev mysql-client mysql-dev \
4
+ && gem install pg mysql2 \
4
5
  && cd /tmp/ \
5
6
  && git clone https://github.com/ninoseki/mihari.git \
6
7
  && cd mihari \
Binary file
@@ -42,7 +42,7 @@ module Mihari
42
42
 
43
43
  def run_emitter(emitter)
44
44
  emitter.run(title: title, description: description, artifacts: unique_artifacts, source: source, tags: tags)
45
- rescue => e
45
+ rescue StandardError => e
46
46
  puts "Emission by #{emitter.class} is failed: #{e}"
47
47
  end
48
48
 
@@ -58,13 +58,13 @@ module Mihari
58
58
  end
59
59
 
60
60
  def ip_lookup
61
- result = api.domains.search(filter: {ipv4: query})
61
+ result = api.domains.search(filter: { ipv4: query })
62
62
  records = result["records"] || []
63
63
  records.map { |record| record["hostname"] }.compact.uniq
64
64
  end
65
65
 
66
66
  def mail_lookup
67
- result = api.domains.search(filter: {whois_email: query})
67
+ result = api.domains.search(filter: { whois_email: query })
68
68
  records = result["records"] || []
69
69
  records.map { |record| record["hostname"] }.compact.uniq
70
70
  end
data/lib/mihari/cli.rb CHANGED
@@ -1,293 +1,73 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
- require "rack/builder"
5
- require "rack/handler/webrick"
6
3
  require "thor"
7
4
 
5
+ require "mihari/commands/binaryedge"
6
+ require "mihari/commands/censys"
7
+ require "mihari/commands/circl"
8
+ require "mihari/commands/crtsh"
9
+ require "mihari/commands/dnpedia"
10
+ require "mihari/commands/dnstwister"
11
+ require "mihari/commands/onyphe"
12
+ require "mihari/commands/otx"
13
+ require "mihari/commands/passivetotal"
14
+ require "mihari/commands/pulsedive"
15
+ require "mihari/commands/securitytrails_domain_feed"
16
+ require "mihari/commands/securitytrails"
17
+ require "mihari/commands/shodan"
18
+ require "mihari/commands/spyse"
19
+ require "mihari/commands/urlscan"
20
+ require "mihari/commands/virustotal"
21
+ require "mihari/commands/zoomeye"
22
+
23
+ require "mihari/commands/free_text"
24
+ require "mihari/commands/http_hash"
25
+ require "mihari/commands/passive_dns"
26
+ require "mihari/commands/passive_ssl"
27
+ require "mihari/commands/reverse_whois"
28
+ require "mihari/commands/ssh_fingerprint"
29
+
30
+ require "mihari/commands/config"
31
+ require "mihari/commands/json"
32
+ require "mihari/commands/web"
33
+
8
34
  module Mihari
9
35
  class CLI < Thor
10
- class_option :config, type: :string, desc: "path to config file"
11
-
12
- def self.exit_on_failure?
13
- true
14
- end
15
-
16
- desc "censys [QUERY]", "Censys IPv4 search by a query"
17
- method_option :title, type: :string, desc: "title"
18
- method_option :description, type: :string, desc: "description"
19
- method_option :tags, type: :array, desc: "tags"
20
- method_option :type, type: :string, desc: "type to search (ipv4 / websites / certificates)", default: "ipv4"
21
- def censys(query)
22
- with_error_handling do
23
- run_analyzer Analyzers::Censys, query: query, options: options
36
+ class_option :config, type: :string, desc: "path to the config file"
37
+
38
+ include Mihari::Commands::BinaryEdge
39
+ include Mihari::Commands::Censys
40
+ include Mihari::Commands::CIRCL
41
+ include Mihari::Commands::Config
42
+ include Mihari::Commands::Crtsh
43
+ include Mihari::Commands::DNPedia
44
+ include Mihari::Commands::DNSTwister
45
+ include Mihari::Commands::FreeText
46
+ include Mihari::Commands::HTTPHash
47
+ include Mihari::Commands::JSON
48
+ include Mihari::Commands::Onyphe
49
+ include Mihari::Commands::OTX
50
+ include Mihari::Commands::PassiveDNS
51
+ include Mihari::Commands::PassiveSSL
52
+ include Mihari::Commands::PassiveTotal
53
+ include Mihari::Commands::Pulsedive
54
+ include Mihari::Commands::ReverseWhois
55
+ include Mihari::Commands::SecurityTrails
56
+ include Mihari::Commands::SecurityTrailsDomainFeed
57
+ include Mihari::Commands::Shodan
58
+ include Mihari::Commands::Spyse
59
+ include Mihari::Commands::SSHFingerprint
60
+ include Mihari::Commands::Urlscan
61
+ include Mihari::Commands::VirusTotal
62
+ include Mihari::Commands::Web
63
+ include Mihari::Commands::ZoomEye
64
+
65
+ class << self
66
+ def exit_on_failure?
67
+ true
24
68
  end
25
69
  end
26
70
 
27
- desc "shodan [QUERY]", "Shodan host search by a query"
28
- method_option :title, type: :string, desc: "title"
29
- method_option :description, type: :string, desc: "description"
30
- method_option :tags, type: :array, desc: "tags"
31
- def shodan(query)
32
- with_error_handling do
33
- run_analyzer Analyzers::Shodan, query: query, options: options
34
- end
35
- end
36
-
37
- desc "onyphe [QUERY]", "Onyphe datascan search by a query"
38
- method_option :title, type: :string, desc: "title"
39
- method_option :description, type: :string, desc: "description"
40
- method_option :tags, type: :array, desc: "tags"
41
- def onyphe(query)
42
- with_error_handling do
43
- run_analyzer Analyzers::Onyphe, query: query, options: options
44
- end
45
- end
46
-
47
- desc "urlscan [QUERY]", "urlscan search by a given query"
48
- method_option :title, type: :string, desc: "title"
49
- method_option :description, type: :string, desc: "description"
50
- method_option :tags, type: :array, desc: "tags"
51
- method_option :filter, type: :string, desc: "filter for urlscan pro search"
52
- method_option :target_type, type: :string, default: "url", desc: "target type to fetch from lookup results (target type should be 'url', 'domain' or 'ip')"
53
- method_option :use_pro, type: :boolean, default: false, desc: "use pro search API or not"
54
- method_option :use_similarity, type: :boolean, default: false, desc: "use similarity API or not"
55
- def urlscan(query)
56
- with_error_handling do
57
- run_analyzer Analyzers::Urlscan, query: query, options: options
58
- end
59
- end
60
-
61
- desc "virustotal [IP|DOMAIN]", "VirusTotal resolutions lookup by an ip or domain"
62
- method_option :title, type: :string, desc: "title"
63
- method_option :description, type: :string, desc: "description"
64
- method_option :tags, type: :array, desc: "tags"
65
- def virustotal(indiactor)
66
- with_error_handling do
67
- run_analyzer Analyzers::VirusTotal, query: refang(indiactor), options: options
68
- end
69
- end
70
-
71
- desc "securitytrails [IP|DOMAIN|EMAIL]", "SecurityTrails lookup by an ip, domain or email"
72
- method_option :title, type: :string, desc: "title"
73
- method_option :description, type: :string, desc: "description"
74
- method_option :tags, type: :array, desc: "tags"
75
- def securitytrails(indiactor)
76
- with_error_handling do
77
- run_analyzer Analyzers::SecurityTrails, query: refang(indiactor), options: options
78
- end
79
- end
80
- map "st" => :securitytrails
81
-
82
- desc "securitytrails_domain_feed [REGEXP]", "SecurityTrails new domain feed search by a regexp"
83
- method_option :title, type: :string, desc: "title"
84
- method_option :description, type: :string, desc: "description"
85
- method_option :tags, type: :array, desc: "tags"
86
- method_option :type, type: :string, default: "registered", desc: "A type of domain feed ('all', 'new' or 'registered')"
87
- def securitytrails_domain_feed(regexp)
88
- with_error_handling do
89
- run_analyzer Analyzers::SecurityTrailsDomainFeed, query: regexp, options: options
90
- end
91
- end
92
- map "st_domain_feed" => :securitytrails_domain_feed
93
-
94
- desc "crtsh [QUERY]", "crt.sh search by a query"
95
- method_option :title, type: :string, desc: "title"
96
- method_option :description, type: :string, desc: "description"
97
- method_option :tags, type: :array, desc: "tags"
98
- method_option :exclude_expired, type: :boolean, desc: "exclude expired certificates"
99
- def crtsh(query)
100
- with_error_handling do
101
- run_analyzer Analyzers::Crtsh, query: query, options: options
102
- end
103
- end
104
-
105
- desc "dnpedia [QUERY]", "DNPedia domain search by a query"
106
- method_option :title, type: :string, desc: "title"
107
- method_option :description, type: :string, desc: "description"
108
- method_option :tags, type: :array, desc: "tags"
109
- def dnpedia(query)
110
- with_error_handling do
111
- run_analyzer Analyzers::DNPedia, query: query, options: options
112
- end
113
- end
114
-
115
- desc "circl [DOMAIN|SHA1]", "CIRCL passive DNS/SSL lookup by a domain or SHA1 certificate fingerprint"
116
- method_option :title, type: :string, desc: "title"
117
- method_option :description, type: :string, desc: "description"
118
- method_option :tags, type: :array, desc: "tags"
119
- def circl(query)
120
- with_error_handling do
121
- run_analyzer Analyzers::CIRCL, query: refang(query), options: options
122
- end
123
- end
124
-
125
- desc "passivetotal [IP|DOMAIN|EMAIL|SHA1]", "PassiveTotal lookup by an ip, domain, email or SHA1 certificate fingerprint"
126
- method_option :title, type: :string, desc: "title"
127
- method_option :description, type: :string, desc: "description"
128
- method_option :tags, type: :array, desc: "tags"
129
- def passivetotal(indicator)
130
- with_error_handling do
131
- run_analyzer Analyzers::PassiveTotal, query: refang(indicator), options: options
132
- end
133
- end
134
-
135
- desc "zoomeye [QUERY]", "ZoomEye search by a query"
136
- method_option :title, type: :string, desc: "title"
137
- method_option :description, type: :string, desc: "description"
138
- method_option :tags, type: :array, desc: "tags"
139
- method_option :type, type: :string, desc: "type to search(host / web)", default: "host"
140
- def zoomeye(query)
141
- with_error_handling do
142
- run_analyzer Analyzers::ZoomEye, query: query, options: options
143
- end
144
- end
145
-
146
- desc "binaryedge [QUERY]", "BinaryEdge host search by a query"
147
- method_option :title, type: :string, desc: "title"
148
- method_option :description, type: :string, desc: "description"
149
- method_option :tags, type: :array, desc: "tags"
150
- def binaryedge(query)
151
- with_error_handling do
152
- run_analyzer Analyzers::BinaryEdge, query: query, options: options
153
- end
154
- end
155
-
156
- desc "pulsedive [IP|DOMAIN]", "Pulsedive lookup by an ip or domain"
157
- method_option :title, type: :string, desc: "title"
158
- method_option :description, type: :string, desc: "description"
159
- method_option :tags, type: :array, desc: "tags"
160
- def pulsedive(indiactor)
161
- with_error_handling do
162
- run_analyzer Analyzers::Pulsedive, query: refang(indiactor), options: options
163
- end
164
- end
165
-
166
- desc "dnstwister [DOMAIN]", "dnstwister lookup by a domain"
167
- method_option :title, type: :string, desc: "title"
168
- method_option :description, type: :string, desc: "description"
169
- method_option :tags, type: :array, desc: "tags"
170
- def dnstwister(domain)
171
- with_error_handling do
172
- run_analyzer Analyzers::DNSTwister, query: refang(domain), options: options
173
- end
174
- end
175
-
176
- desc "otx [IP|DOMAIN]", "OTX lookup by an IP or domain"
177
- method_option :title, type: :string, desc: "title"
178
- method_option :description, type: :string, desc: "description"
179
- method_option :tags, type: :array, desc: "tags"
180
- def otx(domain)
181
- with_error_handling do
182
- run_analyzer Analyzers::OTX, query: refang(domain), options: options
183
- end
184
- end
185
-
186
- desc "spyse [QUERY]", "Spyse search by a query"
187
- method_option :title, type: :string, desc: "title"
188
- method_option :description, type: :string, desc: "description"
189
- method_option :tags, type: :array, desc: "tags"
190
- method_option :type, type: :string, desc: "type to search (ip or domain)", default: "doamin"
191
- def spyse(query)
192
- with_error_handling do
193
- run_analyzer Analyzers::Spyse, query: query, options: options
194
- end
195
- end
196
-
197
- desc "passive_dns [IP|DOMAIN]", "Cross search with passive DNS services by an ip or domain"
198
- method_option :title, type: :string, desc: "title"
199
- method_option :description, type: :string, desc: "description"
200
- method_option :tags, type: :array, desc: "tags"
201
- def passive_dns(query)
202
- with_error_handling do
203
- run_analyzer Analyzers::PassiveDNS, query: refang(query), options: options
204
- end
205
- end
206
-
207
- desc "passive_ssl [SHA1]", "Cross search with passive SSL services by an SHA1 certificate fingerprint"
208
- method_option :title, type: :string, desc: "title"
209
- method_option :description, type: :string, desc: "description"
210
- method_option :tags, type: :array, desc: "tags"
211
- def passive_ssl(query)
212
- with_error_handling do
213
- run_analyzer Analyzers::PassiveSSL, query: query, options: options
214
- end
215
- end
216
-
217
- desc "reverse_whois [EMAIL]", "Cross search with reverse whois services by an email"
218
- method_option :title, type: :string, desc: "title"
219
- method_option :description, type: :string, desc: "description"
220
- method_option :tags, type: :array, desc: "tags"
221
- def reverse_whois(query)
222
- with_error_handling do
223
- run_analyzer Analyzers::ReveseWhois, query: refang(query), options: options
224
- end
225
- end
226
-
227
- desc "http_hash", "Cross search with search engines by a hash of an HTTP response (SHA256, MD5 and MurmurHash3)"
228
- method_option :title, type: :string, desc: "title"
229
- method_option :description, type: :string, desc: "description"
230
- method_option :tags, type: :array, desc: "tags"
231
- method_option :md5, type: :string, desc: "MD5 hash"
232
- method_option :sha256, type: :string, desc: "SHA256 hash"
233
- method_option :mmh3, type: :numeric, desc: "MurmurHash3 hash"
234
- method_option :html, type: :string, desc: "path to an HTML file"
235
- def http_hash
236
- with_error_handling do
237
- run_analyzer Analyzers::HTTPHash, query: nil, options: options
238
- end
239
- end
240
-
241
- desc "free_text [TEXT]", "Cross search with search engines by a free text"
242
- method_option :title, type: :string, desc: "title"
243
- method_option :description, type: :string, desc: "description"
244
- method_option :tags, type: :array, desc: "tags"
245
- def free_text(text)
246
- with_error_handling do
247
- run_analyzer Analyzers::FreeText, query: text, options: options
248
- end
249
- end
250
-
251
- desc "ssh_fingerprint [FINGERPRINT]", "Cross search with search engines by an SSH fingerprint (e.g. dc:14:de:8e:d7:c1:15:43:23:82:25:81:d2:59:e8:c0)"
252
- method_option :title, type: :string, desc: "title"
253
- method_option :description, type: :string, desc: "description"
254
- method_option :tags, type: :array, desc: "tags"
255
- def ssh_fingerprint(fingerprint)
256
- with_error_handling do
257
- run_analyzer Analyzers::SSHFingerprint, query: fingerprint, options: options
258
- end
259
- end
260
-
261
- desc "import_from_json", "Give a JSON input via STDIN"
262
- def import_from_json(input = nil)
263
- with_error_handling do
264
- json = input || $stdin.gets.chomp
265
- raise ArgumentError, "Input not found: please give an input in a JSON format" unless json
266
-
267
- json = parse_as_json(json)
268
- raise ArgumentError, "Invalid input format: an input JSON data should have title, description and artifacts key" unless valid_json?(json)
269
-
270
- title = json["title"]
271
- description = json["description"]
272
- artifacts = json["artifacts"]
273
- tags = json["tags"] || []
274
-
275
- basic = Analyzers::Basic.new(title: title, description: description, artifacts: artifacts, source: "json", tags: tags)
276
- basic.run
277
- end
278
- end
279
-
280
- desc "web", "Launch the web app"
281
- method_option :port, type: :numeric, default: 9292
282
- method_option :host, type: :string, default: "localhost"
283
- def web
284
- port = options["port"].to_i || 9292
285
- host = options["host"] || "localhost"
286
-
287
- load_configuration
288
- Mihari::App.run!(port: port, host: host)
289
- end
290
-
291
71
  no_commands do
292
72
  def with_error_handling
293
73
  yield
@@ -296,12 +76,6 @@ module Mihari
296
76
  notifier.notify e
297
77
  end
298
78
 
299
- def parse_as_json(input)
300
- JSON.parse input
301
- rescue JSON::ParserError => _e
302
- nil
303
- end
304
-
305
79
  # @return [true, false]
306
80
  def valid_json?(json)
307
81
  %w[title description artifacts].all? { |key| json.key? key }