github-safegem 0.1.3 → 0.2.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.
- data/VERSION.yml +2 -2
- data/bin/safegem +61 -19
- data/lib/safegem/exception.rb +10 -0
- data/lib/safegem/security.rb +6 -7
- data/lib/safegem.rb +1 -1
- data/test/safegem_test.rb +31 -21
- metadata +24 -4
data/VERSION.yml
CHANGED
data/bin/safegem
CHANGED
@@ -7,20 +7,36 @@ require 'rubygems/specification'
|
|
7
7
|
require 'sinatra'
|
8
8
|
require 'timeout'
|
9
9
|
require 'yaml'
|
10
|
+
require 'net/http'
|
11
|
+
require 'safegem/exception'
|
12
|
+
require 'json'
|
13
|
+
require 'base64'
|
14
|
+
require 'zlib'
|
15
|
+
|
16
|
+
def time
|
17
|
+
t1 = Time.now
|
18
|
+
yield
|
19
|
+
Time.now - t1
|
20
|
+
end
|
10
21
|
|
11
22
|
post '/' do
|
23
|
+
puts "-> #{params.merge('data' => params[:data].size).inspect}"
|
12
24
|
r, w = IO.pipe
|
13
25
|
|
14
26
|
pid = nil
|
15
27
|
begin
|
16
|
-
repo
|
17
|
-
data
|
18
|
-
|
19
|
-
|
28
|
+
repo = params[:repo]
|
29
|
+
data = params[:data]
|
30
|
+
callback = params[:callback]
|
31
|
+
token = params[:token]
|
32
|
+
tmpdir = "tmp/#{repo}"
|
33
|
+
spec = nil
|
20
34
|
|
21
|
-
Timeout::timeout(
|
22
|
-
`git clone --depth 1 git://github.com/#{repo} #{tmpdir}`
|
35
|
+
Timeout::timeout(300) do
|
36
|
+
t = time { `git clone --depth 1 git://github.com/#{repo} #{tmpdir}` }
|
37
|
+
puts "-- cloned #{repo} in #{t}s"
|
23
38
|
|
39
|
+
t1 = Time.now
|
24
40
|
pid = fork do
|
25
41
|
begin
|
26
42
|
r.close
|
@@ -60,26 +76,52 @@ post '/' do
|
|
60
76
|
spec.validate
|
61
77
|
end
|
62
78
|
|
63
|
-
|
79
|
+
payload = Base64.encode64(Zlib::Deflate.deflate(YAML.dump(spec)))
|
80
|
+
w.write payload
|
81
|
+
w.close
|
64
82
|
rescue Object
|
65
|
-
puts
|
83
|
+
puts $!, $@
|
66
84
|
|
67
85
|
w.write "ERROR: #$!"
|
86
|
+
w.close
|
68
87
|
end
|
69
88
|
end
|
89
|
+
|
70
90
|
w.close
|
91
|
+
Process.wait(pid)
|
92
|
+
yaml = r.read
|
93
|
+
r.close
|
94
|
+
puts "-- converted to yaml in #{Time.now - t1}s"
|
71
95
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
96
|
+
res = nil
|
97
|
+
t = time do
|
98
|
+
payload = {'token' => token, 'yaml' => yaml}
|
99
|
+
puts "<- [#{callback}] #{payload.merge('yaml' => payload['yaml'].size).inspect}"
|
100
|
+
res = Net::HTTP.post_form(URI.parse(callback), payload)
|
101
|
+
end
|
102
|
+
puts "-> #{res.body.inspect} in #{t}s"
|
78
103
|
|
79
|
-
|
104
|
+
# uri = URI.parse(callback)
|
105
|
+
# http = Net::HTTP.new(uri.host)
|
106
|
+
# http.set_debug_output $stdout
|
107
|
+
# http.start do |http|
|
108
|
+
# req = Net::HTTP::Post.new(uri.path)
|
109
|
+
# payload = {'token' => token, 'yaml' => yaml}
|
110
|
+
# req.set_form_data(payload)
|
111
|
+
# res = http.request(req)
|
112
|
+
# p res.value
|
113
|
+
# end
|
114
|
+
|
115
|
+
packet = {'result' => "Successfully converted #{repo} gemspec to YAML.", 'error' => nil}
|
116
|
+
puts "<- #{packet.inspect}"
|
117
|
+
packet.to_json
|
118
|
+
end
|
119
|
+
rescue Exception => e
|
120
|
+
Process.kill(9, pid) rescue nil
|
121
|
+
packet = {'error' => e.to_hash}
|
122
|
+
puts "<- #{packet.inspect}"
|
123
|
+
packet.to_json
|
80
124
|
ensure
|
81
|
-
`rm -rf #{tmpdir}`
|
125
|
+
`rm -rf #{tmpdir}` if tmpdir
|
82
126
|
end
|
83
|
-
end
|
84
|
-
|
85
|
-
Sinatra::Application.run!
|
127
|
+
end
|
data/lib/safegem/security.rb
CHANGED
@@ -45,16 +45,15 @@ class String
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
48
|
# Bug in ruby doesn't check taint when an array of globs is passed
|
51
49
|
class << Dir
|
52
|
-
# we need to track $SAFE level manually because define_method captures the
|
53
|
-
# of the current scope, as it would a local varaible, and of
|
50
|
+
# we need to track $SAFE level manually because define_method captures the
|
51
|
+
# $SAFE level of the current scope, as it would a local varaible, and of
|
52
|
+
# course the current scope has a $SAFE of 0
|
54
53
|
@@safe_level = 0
|
55
54
|
|
56
|
-
# since this method is defined with def instead of define_method, $SAFE will
|
57
|
-
# the calling scope which is what we want
|
55
|
+
# since this method is defined with def instead of define_method, $SAFE will
|
56
|
+
# be taken from the calling scope which is what we want
|
58
57
|
def set_safe_level
|
59
58
|
@@safe_level = $SAFE
|
60
59
|
end
|
@@ -63,7 +62,7 @@ class << Dir
|
|
63
62
|
m = instance_method method_name
|
64
63
|
define_method method_name do |*args|
|
65
64
|
$SAFE = @@safe_level
|
66
|
-
raise SecurityError
|
65
|
+
raise SecurityError if $SAFE >= 3 and args.flatten.any? {|a| a.tainted? }
|
67
66
|
|
68
67
|
m.bind(self).call(*args)
|
69
68
|
end
|
data/lib/safegem.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'safegem/lazy_dir'
|
2
|
-
require 'safegem/security'
|
2
|
+
require 'safegem/security'
|
data/test/safegem_test.rb
CHANGED
@@ -5,14 +5,18 @@ require 'cgi'
|
|
5
5
|
require 'fileutils'
|
6
6
|
require 'open4'
|
7
7
|
|
8
|
-
OUTPUT = !!ENV['
|
9
|
-
puts "safegem
|
8
|
+
OUTPUT = !!ENV['OUTPUT']
|
9
|
+
puts "safegem output disabled, set OUTPUT=1 to enable" if ! OUTPUT
|
10
10
|
|
11
11
|
def mv(a, b)
|
12
12
|
here = File.dirname(__FILE__)
|
13
13
|
FileUtils.mv(File.join(here, a), File.join(here, b))
|
14
14
|
end
|
15
15
|
|
16
|
+
def log(x)
|
17
|
+
puts x if OUTPUT
|
18
|
+
end
|
19
|
+
|
16
20
|
# ensure git_mock is in place before running any of these tests
|
17
21
|
mv('git', 'git_mock') rescue nil
|
18
22
|
|
@@ -24,8 +28,10 @@ class SafeGemTest < Test::Unit::TestCase
|
|
24
28
|
mv('git_mock', 'git')
|
25
29
|
|
26
30
|
# construct the safegem command
|
27
|
-
cmd = "PATH=#{here}:$PATH ruby #{here}/../bin/safegem
|
31
|
+
cmd = "PATH=#{here}:$PATH ruby #{here}/../bin/safegem"
|
28
32
|
cmd += " > /dev/null 2>&1" unless OUTPUT
|
33
|
+
|
34
|
+
log(cmd)
|
29
35
|
|
30
36
|
# run safegem
|
31
37
|
@pid, _, _, _ = Open4::popen4(cmd)
|
@@ -35,7 +41,9 @@ class SafeGemTest < Test::Unit::TestCase
|
|
35
41
|
begin
|
36
42
|
TCPSocket.open('localhost', 4567) {}
|
37
43
|
server_started = true
|
44
|
+
log 'good'
|
38
45
|
rescue Errno::ECONNREFUSED
|
46
|
+
log 'err'
|
39
47
|
server_started = false
|
40
48
|
sleep 0.1
|
41
49
|
retry
|
@@ -44,9 +52,11 @@ class SafeGemTest < Test::Unit::TestCase
|
|
44
52
|
end
|
45
53
|
|
46
54
|
def teardown
|
55
|
+
log "Killing #{@pid}"
|
47
56
|
Process.kill("SIGHUP", @pid)
|
48
57
|
mv('git', 'git_mock')
|
49
58
|
sleep(0.5) # to let sinatra unbind the socket
|
59
|
+
log "Teardown complete"
|
50
60
|
end
|
51
61
|
|
52
62
|
def test_access_to_untainted_locals
|
@@ -55,24 +65,24 @@ class SafeGemTest < Test::Unit::TestCase
|
|
55
65
|
end
|
56
66
|
end
|
57
67
|
|
58
|
-
def test_timeout
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
68
|
+
# def test_timeout
|
69
|
+
# puts "\ntesting 30s timeout"
|
70
|
+
# begin
|
71
|
+
# timeout(32) do
|
72
|
+
# s = req <<-EOS
|
73
|
+
# def forever
|
74
|
+
# loop{}
|
75
|
+
# ensure
|
76
|
+
# forever
|
77
|
+
# end
|
78
|
+
# forever
|
79
|
+
# EOS
|
80
|
+
# assert_equal "ERROR: execution expired", s
|
81
|
+
# end
|
82
|
+
# rescue Timeout::Error
|
83
|
+
# fail "timed out! no good!"
|
84
|
+
# end
|
85
|
+
# end
|
76
86
|
|
77
87
|
def test_legit_gemspec_works
|
78
88
|
gemspec = <<-EOS
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: github-safegem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PJ Hyett
|
@@ -10,10 +10,29 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-03-29 00:00:00 -07:00
|
14
14
|
default_executable: safegem
|
15
|
-
dependencies:
|
16
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: json
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.1.3
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: json
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.9.9.1
|
35
|
+
version:
|
17
36
|
description: GitHub's safe gem eval web service
|
18
37
|
email: tom@mojombo.com
|
19
38
|
executables:
|
@@ -26,6 +45,7 @@ files:
|
|
26
45
|
- VERSION.yml
|
27
46
|
- bin/safegem
|
28
47
|
- lib/safegem
|
48
|
+
- lib/safegem/exception.rb
|
29
49
|
- lib/safegem/lazy_dir.rb
|
30
50
|
- lib/safegem/security.rb
|
31
51
|
- lib/safegem.rb
|