gitrob 0.0.1

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +47 -0
  7. data/Rakefile +2 -0
  8. data/bin/gitrob +258 -0
  9. data/gitrob.gemspec +36 -0
  10. data/lib/gitrob.rb +116 -0
  11. data/lib/gitrob/github/blob.rb +41 -0
  12. data/lib/gitrob/github/http_client.rb +127 -0
  13. data/lib/gitrob/github/organization.rb +93 -0
  14. data/lib/gitrob/github/repository.rb +72 -0
  15. data/lib/gitrob/github/user.rb +78 -0
  16. data/lib/gitrob/observers/sensitive_files.rb +82 -0
  17. data/lib/gitrob/progressbar.rb +52 -0
  18. data/lib/gitrob/util.rb +11 -0
  19. data/lib/gitrob/version.rb +3 -0
  20. data/lib/gitrob/webapp.rb +76 -0
  21. data/models/blob.rb +35 -0
  22. data/models/finding.rb +14 -0
  23. data/models/organization.rb +32 -0
  24. data/models/repo.rb +22 -0
  25. data/models/user.rb +28 -0
  26. data/patterns.json +303 -0
  27. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  28. data/public/fonts/glyphicons-halflings-regular.svg +229 -0
  29. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  30. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  31. data/public/javascripts/bootstrap.min.js +7 -0
  32. data/public/javascripts/gitrob.js +75 -0
  33. data/public/javascripts/jquery-2.1.1.min.js +4 -0
  34. data/public/javascripts/lang-apollo.js +2 -0
  35. data/public/javascripts/lang-basic.js +3 -0
  36. data/public/javascripts/lang-clj.js +18 -0
  37. data/public/javascripts/lang-css.js +2 -0
  38. data/public/javascripts/lang-dart.js +3 -0
  39. data/public/javascripts/lang-erlang.js +2 -0
  40. data/public/javascripts/lang-go.js +1 -0
  41. data/public/javascripts/lang-hs.js +2 -0
  42. data/public/javascripts/lang-lisp.js +3 -0
  43. data/public/javascripts/lang-llvm.js +1 -0
  44. data/public/javascripts/lang-lua.js +2 -0
  45. data/public/javascripts/lang-matlab.js +6 -0
  46. data/public/javascripts/lang-ml.js +2 -0
  47. data/public/javascripts/lang-mumps.js +2 -0
  48. data/public/javascripts/lang-n.js +4 -0
  49. data/public/javascripts/lang-pascal.js +3 -0
  50. data/public/javascripts/lang-proto.js +1 -0
  51. data/public/javascripts/lang-r.js +2 -0
  52. data/public/javascripts/lang-rd.js +1 -0
  53. data/public/javascripts/lang-scala.js +2 -0
  54. data/public/javascripts/lang-sql.js +2 -0
  55. data/public/javascripts/lang-tcl.js +3 -0
  56. data/public/javascripts/lang-tex.js +1 -0
  57. data/public/javascripts/lang-vb.js +2 -0
  58. data/public/javascripts/lang-vhdl.js +3 -0
  59. data/public/javascripts/lang-wiki.js +2 -0
  60. data/public/javascripts/lang-xq.js +3 -0
  61. data/public/javascripts/lang-yaml.js +2 -0
  62. data/public/javascripts/prettify.js +30 -0
  63. data/public/javascripts/run_prettify.js +34 -0
  64. data/public/stylesheets/bootstrap.min.css +7 -0
  65. data/public/stylesheets/bootstrap.min.css.vanilla +5 -0
  66. data/public/stylesheets/gitrob.css +88 -0
  67. data/public/stylesheets/prettify.css +51 -0
  68. data/spec/lib/gitrob/observers/sensitive_files_spec.rb +558 -0
  69. data/spec/spec_helper.rb +127 -0
  70. data/views/blob.erb +22 -0
  71. data/views/index.erb +32 -0
  72. data/views/layout.erb +30 -0
  73. data/views/organization.erb +126 -0
  74. data/views/repository.erb +51 -0
  75. data/views/user.erb +51 -0
  76. metadata +317 -0
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+
3
+ module Gitrob
4
+ class ProgressBar
5
+ TITLE_MAX_LENGTH = 25
6
+
7
+ def initialize(message, options)
8
+ @options = {
9
+ :format => " #{Paint['[*]', :bright, :blue]} %c/%C %B %j% %e",
10
+ :progress_mark => Paint['▓', :bright, :blue],
11
+ :remainder_mark => '░',
12
+ }.merge(options)
13
+ Gitrob::status(message)
14
+ @mutex = Mutex.new
15
+ @progress_bar = ::ProgressBar::Base.new(@options)
16
+ end
17
+
18
+ def finish!
19
+ @mutex.synchronize { @progress_bar.finish }
20
+ end
21
+
22
+ def log(message)
23
+ @mutex.synchronize do
24
+ @progress_bar.log(" #{Paint['[>]', :bright, :blue]} #{message}")
25
+ end
26
+ end
27
+
28
+ def log_error(message)
29
+ @mutex.synchronize do
30
+ @progress_bar.log(" #{Paint['[!]', :bright, :red]} #{message}")
31
+ end
32
+ end
33
+
34
+ def method_missing(method, *args, &block)
35
+ if @progress_bar.respond_to?(method)
36
+ @mutex.synchronize { @progress_bar.send(method, *args, &block) }
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def make_title(t)
45
+ t = t.to_s
46
+ if t.size > TITLE_MAX_LENGTH
47
+ t = "#{t[0, (TITLE_MAX_LENGTH-3)]}..."
48
+ end
49
+ " #{Paint['[>]', :bright, :blue]} #{Paint[t.rjust(TITLE_MAX_LENGTH), :bright, :blue]}"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ module Gitrob
2
+ module Util
3
+ def self.pluralize(count, singular, plural)
4
+ if count.to_i == 1
5
+ "#{count} #{singular}"
6
+ else
7
+ "#{count} #{plural}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Gitrob
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,76 @@
1
+ module Gitrob
2
+ class WebApp < Sinatra::Base
3
+ set :logging, false
4
+ set :sessions, false
5
+ set :app_file, __FILE__
6
+ set :root, File.expand_path("#{File.dirname(__FILE__)}/../../")
7
+ set :public_folder, Proc.new { File.join(root, "public") }
8
+ set :views, Proc.new { File.join(root, "views") }
9
+ set :run, Proc.new { false }
10
+
11
+ helpers do
12
+ HUMAN_PREFIXES = %W(TB GB MB KB B).freeze
13
+
14
+ alias_method :h, :escape_html
15
+
16
+ def number_to_human_size(number)
17
+ s = number.to_f
18
+ i = HUMAN_PREFIXES.length - 1
19
+ while s > 512 && i > 0
20
+ i -= 1
21
+ s /= 1024
22
+ end
23
+ ((s > 9 || s.modulo(1) < 0.1 ? '%d' : '%.1f') % s) + ' ' + HUMAN_PREFIXES[i]
24
+ end
25
+
26
+ def format_path(path)
27
+ dirname = File.dirname(path)
28
+ basename = File.basename(path)
29
+ if dirname == '.'
30
+ "<strong>#{h basename}</strong>"
31
+ else
32
+ "#{h dirname}/<strong>#{h basename}</strong>"
33
+ end
34
+ end
35
+ end
36
+
37
+ before do
38
+ response.headers['Content-Security-Policy'] = "default-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'"
39
+ response.headers['X-Content-Security-Policy'] = "default-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'"
40
+ response.headers['X-WebKit-CSP'] = "default-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'"
41
+ end
42
+
43
+ get '/' do
44
+ @orgs = Gitrob::Organization.all(:order => [:created_at.desc])
45
+ erb :index
46
+ end
47
+
48
+ get '/orgs/:id' do
49
+ @org = Gitrob::Organization.get(params['id'])
50
+ @blobs_with_findings = @org.blobs.all(:findings_count.gt => 0)
51
+ @repos = @org.repos.all(:order => [:owner_name, :name])
52
+ erb :organization
53
+ end
54
+
55
+ get '/repos/:id' do
56
+ @repo = Gitrob::Repo.get(params['id'])
57
+ erb :repository
58
+ end
59
+
60
+ get '/ajax/users/:username' do
61
+ if params['type'] == 'org'
62
+ @user = Gitrob::Organization.first(:name => params['username'])
63
+ @repos = @user.repos.all(:user => nil)
64
+ else
65
+ @user = Gitrob::User.first(:username => params['username'])
66
+ @repos = @user.repos.all
67
+ end
68
+ erb :user, :layout => false
69
+ end
70
+
71
+ get '/ajax/blobs/:id' do
72
+ @blob = Gitrob::Blob.get(params['id'])
73
+ erb :blob, :layout => false
74
+ end
75
+ end
76
+ end
data/models/blob.rb ADDED
@@ -0,0 +1,35 @@
1
+ module Gitrob
2
+ class Blob
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :path, String, :length => 1024, :index => true
7
+ property :filename, String, :length => 255, :index => true
8
+ property :extension, String, :length => 255, :index => true
9
+ property :size, Integer, :index => true
10
+ property :findings_count, Integer, :index => true, :default => 0
11
+ property :created_at, DateTime
12
+
13
+ has n, :findings, :constraint => :destroy
14
+ belongs_to :repo
15
+ belongs_to :organization
16
+
17
+ def url
18
+ "https://github.com/#{URI.escape(owner_name)}/#{URI.escape(repo.name)}/blob/master/#{URI.escape(path)}"
19
+ end
20
+
21
+ def owner_name
22
+ repo.user.nil? ? repo.organization.login : repo.user.username
23
+ end
24
+
25
+ def content
26
+ @content ||= fetch_content
27
+ end
28
+
29
+ private
30
+
31
+ def fetch_content
32
+ HTTParty.get("https://raw.githubusercontent.com/#{URI.escape(owner_name)}/#{URI.escape(repo.name)}/master/#{URI.escape(path)}").body
33
+ end
34
+ end
35
+ end
data/models/finding.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Gitrob
2
+ class Finding
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :caption, String, :length => 255
7
+ property :description, Text
8
+
9
+ belongs_to :blob
10
+ belongs_to :repo
11
+ belongs_to :user, :required => false
12
+ belongs_to :organization
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module Gitrob
2
+ class Organization
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :name, String, :length => 255, :index => true
7
+ property :login, String, :length => 255, :index => true
8
+ property :website, String, :length => 255
9
+ property :location, String, :length => 255
10
+ property :email, String, :length => 255
11
+ property :avatar_url, String, :length => 255
12
+ property :url, String, :length => 255
13
+ property :created_at, DateTime
14
+
15
+ has n, :repos, :constraint => :destroy
16
+ has n, :users, :constraint => :destroy
17
+ has n, :blobs, :constraint => :destroy
18
+ has n, :findings, :constraint => :destroy
19
+
20
+ def username
21
+ @login
22
+ end
23
+
24
+ def bio
25
+ nil
26
+ end
27
+
28
+ def name
29
+ @name.to_s.empty? ? @login : @name
30
+ end
31
+ end
32
+ end
data/models/repo.rb ADDED
@@ -0,0 +1,22 @@
1
+ module Gitrob
2
+ class Repo
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :name, String, :index => true, :length => 255
7
+ property :owner_name, String, :index => true
8
+ property :description, String, :length => 1024
9
+ property :website, String, :length => 255
10
+ property :url, String, :length => 255
11
+ property :created_at, DateTime
12
+
13
+ has n, :blobs, :constraint => :destroy
14
+ has n, :findings, :constraint => :destroy
15
+ belongs_to :user, :required => false
16
+ belongs_to :organization
17
+
18
+ def full_name
19
+ [owner_name, name].join('/')
20
+ end
21
+ end
22
+ end
data/models/user.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Gitrob
2
+ class User
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :username, String, :index => true
7
+ property :name, String, :index => true, :length => 255
8
+ property :website, String, :length => 255
9
+ property :location, String, :length => 512
10
+ property :email, String, :length => 255
11
+ property :avatar_url, String, :length => 255
12
+ property :url, String, :length => 255
13
+ property :bio, String, :length => 1024
14
+ property :created_at, DateTime
15
+
16
+ has n, :repos, :constraint => :destroy
17
+ has n, :blobs, :constraint => :destroy, :through => :repos
18
+ has n, :findings, :constraint => :destroy
19
+ belongs_to :organization, :required => false
20
+
21
+ def name
22
+ if @name.empty?
23
+ return @username
24
+ end
25
+ super
26
+ end
27
+ end
28
+ end
data/patterns.json ADDED
@@ -0,0 +1,303 @@
1
+ [
2
+ {
3
+ "part": "filename",
4
+ "type": "match",
5
+ "pattern": "id_rsa",
6
+ "caption": "Private SSH key",
7
+ "description": null
8
+ },
9
+ {
10
+ "part": "filename",
11
+ "type": "match",
12
+ "pattern": "id_ed25519",
13
+ "caption": "Private SSH key",
14
+ "description": null
15
+ },
16
+ {
17
+ "part": "filename",
18
+ "type": "match",
19
+ "pattern": "id_ecdsa",
20
+ "caption": "Private SSH key",
21
+ "description": null
22
+ },
23
+ {
24
+ "part": "extension",
25
+ "type": "match",
26
+ "pattern": "pem",
27
+ "caption": "Potential cryptographic private key",
28
+ "description": null
29
+ },
30
+ {
31
+ "part": "extension",
32
+ "type": "match",
33
+ "pattern": "key",
34
+ "caption": "Potential cryptographic private key",
35
+ "description": null
36
+ },
37
+ {
38
+ "part": "extension",
39
+ "type": "match",
40
+ "pattern": "pkcs12",
41
+ "caption": "Potential cryptographic key bundle",
42
+ "description": null
43
+ },
44
+ {
45
+ "part": "extension",
46
+ "type": "match",
47
+ "pattern": "pfx",
48
+ "caption": "Potential cryptographic key bundle",
49
+ "description": null
50
+ },
51
+ {
52
+ "part": "extension",
53
+ "type": "match",
54
+ "pattern": "p12",
55
+ "caption": "Potential cryptographic key bundle",
56
+ "description": null
57
+ },
58
+ {
59
+ "part": "extension",
60
+ "type": "match",
61
+ "pattern": "asc",
62
+ "caption": "Potential cryptographic key bundle",
63
+ "description": null
64
+ },
65
+ {
66
+ "part": "filename",
67
+ "type": "match",
68
+ "pattern": "otr.private_key",
69
+ "caption": "Pidgin OTR private key",
70
+ "description": null
71
+ },
72
+ {
73
+ "part": "filename",
74
+ "type": "regex",
75
+ "pattern": "\\A\\.?(bash_|zsh_|z)?history\\z",
76
+ "caption": "Shell command history file",
77
+ "description": null
78
+ },
79
+ {
80
+ "part": "filename",
81
+ "type": "regex",
82
+ "pattern": "\\A\\.?mysql_history\\z",
83
+ "caption": "MySQL client command history file",
84
+ "description": null
85
+ },
86
+ {
87
+ "part": "filename",
88
+ "type": "regex",
89
+ "pattern": "\\A\\.?psql_history\\z",
90
+ "caption": "PostgreSQL client command history file",
91
+ "description": null
92
+ },
93
+ {
94
+ "part": "filename",
95
+ "type": "regex",
96
+ "pattern": "\\A\\.?irb_history\\z",
97
+ "caption": "Ruby IRB console history file",
98
+ "description": null
99
+ },
100
+ {
101
+ "part": "path",
102
+ "type": "regex",
103
+ "pattern": "\\.?purple\\/accounts\\.xml\\z",
104
+ "caption": "Pidgin chat client account configuration file",
105
+ "description": null
106
+ },
107
+ {
108
+ "part": "path",
109
+ "type": "regex",
110
+ "pattern": "\\.?xchat2?\\/servlist_?\\.conf\\z",
111
+ "caption": "Hexchat/XChat IRC client server list configuration file",
112
+ "description": null
113
+ },
114
+ {
115
+ "part": "path",
116
+ "type": "regex",
117
+ "pattern": "\\.?irrsi\\/config\\z",
118
+ "caption": "Irrsi IRC client configuration file",
119
+ "description": null
120
+ },
121
+ {
122
+ "part": "path",
123
+ "type": "regex",
124
+ "pattern": "\\.?recon-ng\\/keys\\.db\\z",
125
+ "caption": "Recon-ng web reconnaissance framework API key database",
126
+ "description": null
127
+ },
128
+ {
129
+ "part": "filename",
130
+ "type": "regex",
131
+ "pattern": "\\A\\.?dbeaver-data-sources.xml\\z",
132
+ "caption": "DBeaver SQL database manager configuration file",
133
+ "description": null
134
+ },
135
+ {
136
+ "part": "filename",
137
+ "type": "regex",
138
+ "pattern": "\\A\\.?muttrc\\z",
139
+ "caption": "Mutt e-mail client configuration file",
140
+ "description": null
141
+ },
142
+ {
143
+ "part": "filename",
144
+ "type": "regex",
145
+ "pattern": "\\A\\.?s3cfg\\z",
146
+ "caption": "S3cmd configuration file",
147
+ "description": null
148
+ },
149
+ {
150
+ "part": "filename",
151
+ "type": "regex",
152
+ "pattern": "\\A\\.?trc\\z",
153
+ "caption": "T command-line Twitter client configuration file",
154
+ "description": null
155
+ },
156
+ {
157
+ "part": "extension",
158
+ "type": "match",
159
+ "pattern": "ovpn",
160
+ "caption": "OpenVPN client configuration file",
161
+ "description": null
162
+ },
163
+ {
164
+ "part": "filename",
165
+ "type": "regex",
166
+ "pattern": "\\A\\.?gitrobrc\\z",
167
+ "caption": "Well, this is awkward... Gitrob configuration file",
168
+ "description": null
169
+ },
170
+ {
171
+ "part": "filename",
172
+ "type": "regex",
173
+ "pattern": "\\A\\.?(bash|zsh)rc\\z",
174
+ "caption": "Shell configuration file",
175
+ "description": "Shell configuration files might contain information such as server hostnames, passwords and API keys."
176
+ },
177
+ {
178
+ "part": "filename",
179
+ "type": "regex",
180
+ "pattern": "\\A\\.?(bash_|zsh_)?profile\\z",
181
+ "caption": "Shell profile configuration file",
182
+ "description": "Shell configuration files might contain information such as server hostnames, passwords and API keys."
183
+ },
184
+ {
185
+ "part": "filename",
186
+ "type": "regex",
187
+ "pattern": "\\A\\.?(bash_|zsh_)?aliases\\z",
188
+ "caption": "Shell command alias configuration file",
189
+ "description": "Shell configuration files might contain information such as server hostnames, passwords and API keys."
190
+ },
191
+ {
192
+ "part": "filename",
193
+ "type": "match",
194
+ "pattern": "secret_token.rb",
195
+ "caption": "Ruby On Rails secret token configuration file",
196
+ "description": "If the Rails secret token is known, it can allow for remote code execution. (http://www.exploit-db.com/exploits/27527/)"
197
+ },
198
+ {
199
+ "part": "filename",
200
+ "type": "match",
201
+ "pattern": "omniauth.rb",
202
+ "caption": "OmniAuth configuration file",
203
+ "description": "The OmniAuth configuration file might contain client application secrets."
204
+ },
205
+ {
206
+ "part": "filename",
207
+ "type": "match",
208
+ "pattern": "carrierwave.rb",
209
+ "caption": "Carrierwave configuration file",
210
+ "description": "Can contain credentials for online storage systems such as Amazon S3 and Google Storage."
211
+ },
212
+ {
213
+ "part": "filename",
214
+ "type": "match",
215
+ "pattern": "schema.rb",
216
+ "caption": "Ruby On Rails database schema file",
217
+ "description": "Contains information on the database schema of a Ruby On Rails application."
218
+ },
219
+ {
220
+ "part": "filename",
221
+ "type": "match",
222
+ "pattern": "database.yml",
223
+ "caption": "Potential Ruby On Rails database configuration file",
224
+ "description": "Might contain database credentials."
225
+ },
226
+ {
227
+ "part": "extension",
228
+ "type": "match",
229
+ "pattern": "kdb",
230
+ "caption": "KeePass password manager database file",
231
+ "description": null
232
+ },
233
+ {
234
+ "part": "extension",
235
+ "type": "match",
236
+ "pattern": "agilekeychain",
237
+ "caption": "1Password password manager database file",
238
+ "description": null
239
+ },
240
+ {
241
+ "part": "extension",
242
+ "type": "match",
243
+ "pattern": "keychain",
244
+ "caption": "Apple Keychain database file",
245
+ "description": null
246
+ },
247
+ {
248
+ "part": "extension",
249
+ "type": "regex",
250
+ "pattern": "\\Akey(store|ring)\\z",
251
+ "caption": "GNOME Keyring database file",
252
+ "description": null
253
+ },
254
+ {
255
+ "part": "extension",
256
+ "type": "match",
257
+ "pattern": "log",
258
+ "caption": "Log file",
259
+ "description": "Log files might contain information such as references to secret HTTP endpoints, session IDs, user information, passwords and API keys."
260
+ },
261
+ {
262
+ "part": "extension",
263
+ "type": "match",
264
+ "pattern": "pcap",
265
+ "caption": "Network traffic capture file",
266
+ "description": null
267
+ },
268
+ {
269
+ "part": "extension",
270
+ "type": "regex",
271
+ "pattern": "\\Asql(dump)?\\z",
272
+ "caption": "SQL dump file",
273
+ "description": null
274
+ },
275
+ {
276
+ "part": "extension",
277
+ "type": "match",
278
+ "pattern": "gnucash",
279
+ "caption": "GnuCash database file",
280
+ "description": null
281
+ },
282
+ {
283
+ "part": "filename",
284
+ "type": "regex",
285
+ "pattern": "backup",
286
+ "caption": "Contains word: backup",
287
+ "description": null
288
+ },
289
+ {
290
+ "part": "filename",
291
+ "type": "regex",
292
+ "pattern": "dump",
293
+ "caption": "Contains word: dump",
294
+ "description": null
295
+ },
296
+ {
297
+ "part": "filename",
298
+ "type": "regex",
299
+ "pattern": "password",
300
+ "caption": "Contains word: password",
301
+ "description": null
302
+ }
303
+ ]