safe_shell 1.0.2 → 1.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +17 -0
- data/{README.rdoc → README.md} +44 -24
- data/Rakefile +1 -1
- data/lib/safe_shell/version.rb +1 -1
- data/lib/safe_shell.rb +2 -6
- data/safe_shell.gemspec +4 -4
- data/spec/safe_shell_spec.rb +11 -11
- metadata +43 -62
- data/Gemfile.lock +0 -24
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b3fdb9a174112b5c8ae48551f3b94932c186068b
|
4
|
+
data.tar.gz: 272aaa99838b8b4adafd61d7bb96ee16c1ab6fb9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17953a6a491bfce79e6ac3147dd24b6fb8314a223392144181eec5d67bd328f4776aff1255178fe15d4fe6b8a488c6ff97ce261d159bb13cd724c5ab04322a52
|
7
|
+
data.tar.gz: 92a715210c58ea17f7422c2e7457d151258d783461e6c4655e3017c61f1d16d471ef1d91e7e0aae75771aea8665bf96b918f68569c47ba64171f11a9d641501b
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/{README.rdoc → README.md}
RENAMED
@@ -1,44 +1,64 @@
|
|
1
|
-
|
1
|
+
# SafeShell
|
2
2
|
|
3
3
|
SafeShell lets you execute shell commands and get the resulting output, but without the security problems of Ruby's backtick operator.
|
4
4
|
|
5
|
-
|
5
|
+
## Usage
|
6
6
|
|
7
|
-
|
7
|
+
Install gem:
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
```
|
10
|
+
gem install safe_shell
|
11
|
+
```
|
12
|
+
|
13
|
+
Use gem:
|
14
|
+
|
15
|
+
```
|
16
|
+
require 'safe_shell'
|
17
|
+
SafeShell.execute("echo", "Hello, world!")
|
18
|
+
```
|
11
19
|
|
12
20
|
SafeShell sets the $? operator to the process status, in the same manner as the backtick operator.
|
13
21
|
|
14
|
-
|
15
|
-
|
22
|
+
```
|
23
|
+
# Send stdout and stderr to files:
|
24
|
+
SafeShell.execute("echo", "Hello, world!", :stdout => "output.txt", :stderr => "error.txt")
|
16
25
|
|
17
|
-
|
18
|
-
|
26
|
+
# Return true if the command exits with a zero status:
|
27
|
+
SafeShell.execute?("echo", "Hello, world!")
|
19
28
|
|
20
|
-
|
21
|
-
|
29
|
+
# Raise an exception if the command exits with a non-zero status:
|
30
|
+
SafeShell.execute!("echo", "Hello, world!")
|
31
|
+
```
|
22
32
|
|
23
|
-
|
33
|
+
## Why?
|
24
34
|
|
25
35
|
If you use backticks to process a file supplied by a user, a carefully crafted filename could allow execution of an arbitrary command:
|
26
36
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
37
|
+
```
|
38
|
+
file = ";blah"
|
39
|
+
`echo #{file}`
|
40
|
+
sh: blah: command not found
|
41
|
+
=> "\n"
|
42
|
+
```
|
31
43
|
|
32
44
|
SafeShell solves this.
|
33
45
|
|
34
|
-
|
35
|
-
|
46
|
+
```
|
47
|
+
SafeShell.execute("echo", file)
|
48
|
+
=> ";blah\n"
|
49
|
+
```
|
50
|
+
|
51
|
+
## Compatibility
|
52
|
+
|
53
|
+
Tested with Ruby 2.0.0 or newer, but it should be happy on pretty much any Ruby version. Maybe not so much on Windows.
|
36
54
|
|
37
|
-
|
55
|
+
## Test
|
38
56
|
|
39
|
-
|
57
|
+
```
|
58
|
+
bundle exec rake
|
59
|
+
````
|
40
60
|
|
41
|
-
|
61
|
+
## Developing
|
42
62
|
|
43
63
|
* Fork the project.
|
44
64
|
* Make your feature addition or bug fix.
|
@@ -48,10 +68,10 @@ Tested with Ruby 1.8.7, but it should be happy on pretty much any Ruby version.
|
|
48
68
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
49
69
|
* Send me a pull request. Bonus points for topic branches.
|
50
70
|
|
51
|
-
|
71
|
+
## Status
|
52
72
|
|
53
73
|
In use on at least one big site, so should be pretty solid. There's not much to it, so I'm not expecting there'll be many releases.
|
54
74
|
|
55
|
-
|
75
|
+
## Copyright
|
56
76
|
|
57
|
-
Copyright (c) 2010 Envato, Ian Leitch, & Pete Yandell. See LICENSE for details.
|
77
|
+
Copyright (c) 2010 - 2015 Envato, Ian Leitch, & Pete Yandell. See LICENSE for details.
|
data/Rakefile
CHANGED
data/lib/safe_shell/version.rb
CHANGED
data/lib/safe_shell.rb
CHANGED
@@ -6,12 +6,8 @@ module SafeShell
|
|
6
6
|
read_end, write_end = IO.pipe
|
7
7
|
new_stdout = opts[:stdout] ? File.open(opts[:stdout], "w+") : write_end
|
8
8
|
new_stderr = opts[:stderr] ? File.open(opts[:stderr], "w+") : write_end
|
9
|
-
|
10
|
-
|
11
|
-
STDOUT.reopen(new_stdout)
|
12
|
-
STDERR.reopen(new_stderr)
|
13
|
-
exec(command, *(args.map { |a| a.to_s }))
|
14
|
-
end
|
9
|
+
opts = {:in => read_end, :out => new_stdout, :err => new_stderr}
|
10
|
+
pid = spawn(command, *(args.map { |a| a.to_s }), opts)
|
15
11
|
write_end.close
|
16
12
|
output = read_end.read
|
17
13
|
Process.waitpid(pid)
|
data/safe_shell.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
$:.push File.expand_path("../lib", __FILE__)
|
3
2
|
require "safe_shell/version"
|
4
3
|
|
@@ -11,14 +10,15 @@ Gem::Specification.new do |s|
|
|
11
10
|
s.homepage = "http://github.com/envato/safe_shell"
|
12
11
|
s.summary = %q{Safely execute shell commands and get their output.}
|
13
12
|
s.description = %q{Execute shell commands and get the resulting output, but without the security problems of Ruby’s backtick operator.}
|
13
|
+
s.license = "MIT"
|
14
14
|
|
15
15
|
s.add_development_dependency "rspec"
|
16
16
|
|
17
|
-
s.rubyforge_project = "safe_shell"
|
18
|
-
|
19
17
|
s.files = `git ls-files`.split("\n")
|
20
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
20
|
s.require_paths = ["lib"]
|
23
|
-
s.extra_rdoc_files = ["LICENSE", "README.
|
21
|
+
s.extra_rdoc_files = ["LICENSE", "README.md"]
|
22
|
+
|
23
|
+
s.required_ruby_version = ">= 2.0.0"
|
24
24
|
end
|
data/spec/safe_shell_spec.rb
CHANGED
@@ -3,23 +3,23 @@ require 'safe_shell'
|
|
3
3
|
describe "SafeShell" do
|
4
4
|
|
5
5
|
it "should return the output of the command" do
|
6
|
-
SafeShell.execute("echo", "Hello, world!").
|
6
|
+
expect(SafeShell.execute("echo", "Hello, world!")).to eql("Hello, world!\n")
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should safely handle dangerous characters in command arguments" do
|
10
|
-
SafeShell.execute("echo", ";date").
|
10
|
+
expect(SafeShell.execute("echo", ";date")).to eql(";date\n")
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should set $? to the exit status of the command" do
|
14
14
|
SafeShell.execute("test", "a", "=", "a")
|
15
|
-
$?.exitstatus.
|
15
|
+
expect($?.exitstatus).to eql(0)
|
16
16
|
|
17
17
|
SafeShell.execute("test", "a", "=", "b")
|
18
|
-
$?.exitstatus.
|
18
|
+
expect($?.exitstatus).to eql(1)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should handle a Pathname object passed as an argument" do
|
22
|
-
expect { SafeShell.execute("ls", Pathname.new("/tmp")) }.
|
22
|
+
expect { SafeShell.execute("ls", Pathname.new("/tmp")) }.not_to raise_error
|
23
23
|
end
|
24
24
|
|
25
25
|
context "output redirection" do
|
@@ -29,26 +29,26 @@ describe "SafeShell" do
|
|
29
29
|
|
30
30
|
it "should let you redirect stdout to a file" do
|
31
31
|
SafeShell.execute("echo", "Hello, world!", :stdout => "tmp/output.txt")
|
32
|
-
File.exists?("tmp/output.txt").
|
33
|
-
File.read("tmp/output.txt").
|
32
|
+
expect(File.exists?("tmp/output.txt")).to eql(true)
|
33
|
+
expect(File.read("tmp/output.txt")).to eql("Hello, world!\n")
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should let you redirect stderr to a file" do
|
37
37
|
SafeShell.execute("cat", "tmp/nonexistent-file", :stderr => "tmp/output.txt")
|
38
|
-
File.exists?("tmp/output.txt").
|
39
|
-
File.read("tmp/output.txt").
|
38
|
+
expect(File.exists?("tmp/output.txt")).to eql(true)
|
39
|
+
expect(File.read("tmp/output.txt")).to eql("cat: tmp/nonexistent-file: No such file or directory\n")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
context ".execute!" do
|
44
44
|
it "returns the output of the command" do
|
45
|
-
SafeShell.execute!("echo", "Hello, world!").
|
45
|
+
expect(SafeShell.execute!("echo", "Hello, world!")).to eql("Hello, world!\n")
|
46
46
|
end
|
47
47
|
|
48
48
|
it "raises an exception of the command fails" do
|
49
49
|
expect {
|
50
50
|
SafeShell.execute!("test", "a", "=", "b")
|
51
|
-
}.
|
51
|
+
}.to raise_error(SafeShell::CommandFailedException)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
metadata
CHANGED
@@ -1,56 +1,47 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_shell
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 2
|
10
|
-
version: 1.0.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.3
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Envato
|
14
8
|
- Ian Leitch
|
15
9
|
- Pete Yandell
|
16
10
|
autorequire:
|
17
11
|
bindir: bin
|
18
12
|
cert_chain: []
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
dependencies:
|
23
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2015-10-30 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
24
16
|
name: rspec
|
25
|
-
|
26
|
-
|
27
|
-
none: false
|
28
|
-
requirements:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
29
19
|
- - ">="
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
|
32
|
-
segments:
|
33
|
-
- 0
|
34
|
-
version: "0"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
35
22
|
type: :development
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
description: Execute shell commands and get the resulting output, but without the
|
30
|
+
security problems of Ruby’s backtick operator.
|
31
|
+
email:
|
39
32
|
- pete@notahat.com
|
40
33
|
executables: []
|
41
|
-
|
42
34
|
extensions: []
|
43
|
-
|
44
|
-
extra_rdoc_files:
|
35
|
+
extra_rdoc_files:
|
45
36
|
- LICENSE
|
46
|
-
- README.
|
47
|
-
files:
|
48
|
-
- .document
|
49
|
-
- .gitignore
|
37
|
+
- README.md
|
38
|
+
files:
|
39
|
+
- ".document"
|
40
|
+
- ".gitignore"
|
41
|
+
- ".travis.yml"
|
50
42
|
- Gemfile
|
51
|
-
- Gemfile.lock
|
52
43
|
- LICENSE
|
53
|
-
- README.
|
44
|
+
- README.md
|
54
45
|
- Rakefile
|
55
46
|
- lib/safe_shell.rb
|
56
47
|
- lib/safe_shell/version.rb
|
@@ -58,40 +49,30 @@ files:
|
|
58
49
|
- spec/safe_shell_spec.rb
|
59
50
|
- spec/spec.opts
|
60
51
|
- tmp/.gitkeep
|
61
|
-
has_rdoc: true
|
62
52
|
homepage: http://github.com/envato/safe_shell
|
63
|
-
licenses:
|
64
|
-
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
65
56
|
post_install_message:
|
66
57
|
rdoc_options: []
|
67
|
-
|
68
|
-
require_paths:
|
58
|
+
require_paths:
|
69
59
|
- lib
|
70
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
-
|
72
|
-
requirements:
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
73
62
|
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
version: "0"
|
79
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
|
-
requirements:
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.0.0
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
82
67
|
- - ">="
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
|
85
|
-
segments:
|
86
|
-
- 0
|
87
|
-
version: "0"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
88
70
|
requirements: []
|
89
|
-
|
90
|
-
|
91
|
-
rubygems_version: 1.6.2
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.4.5
|
92
73
|
signing_key:
|
93
|
-
specification_version:
|
74
|
+
specification_version: 4
|
94
75
|
summary: Safely execute shell commands and get their output.
|
95
|
-
test_files:
|
76
|
+
test_files:
|
96
77
|
- spec/safe_shell_spec.rb
|
97
78
|
- spec/spec.opts
|
data/Gemfile.lock
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
safe_shell (1.0.1)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: http://rubygems.org/
|
8
|
-
specs:
|
9
|
-
diff-lcs (1.1.2)
|
10
|
-
rspec (2.5.0)
|
11
|
-
rspec-core (~> 2.5.0)
|
12
|
-
rspec-expectations (~> 2.5.0)
|
13
|
-
rspec-mocks (~> 2.5.0)
|
14
|
-
rspec-core (2.5.1)
|
15
|
-
rspec-expectations (2.5.0)
|
16
|
-
diff-lcs (~> 1.1.2)
|
17
|
-
rspec-mocks (2.5.0)
|
18
|
-
|
19
|
-
PLATFORMS
|
20
|
-
ruby
|
21
|
-
|
22
|
-
DEPENDENCIES
|
23
|
-
rspec
|
24
|
-
safe_shell!
|