gitrob 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ ]