paraxial 0.4.0 → 0.6.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.
- checksums.yaml +4 -4
- data/lib/paraxial/checker.rb +18 -10
- data/lib/paraxial/cli.rb +10 -8
- data/lib/paraxial/helpers.rb +8 -0
- data/lib/paraxial/initializers/marshal_patch.rb +37 -0
- data/lib/paraxial/initializers/startup.rb +9 -6
- data/lib/paraxial/version.rb +1 -1
- data/lib/paraxial.rb +41 -1
- data/lib/rubocop/cop/paraxial/raw.rb +22 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ef49572c0555fdaea4bc13d94f4faa2d771a9919ee54304d832b5b97306cc09
|
4
|
+
data.tar.gz: 3bd3f48e2517d1c309e8c57ec8814a6bf9077506c461904c5f38f1ecc7e35dd3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ed1f565c95cffdc6e8940d2c92c1cee7c7cd6157fe5da9f304746a65c1687ca74141483add2ca13616cfe82371a27b396ae4fcb178dffb80cac014ace5ac152
|
7
|
+
data.tar.gz: aa3ab3d9ff75cd0ff804a859eebd847ca60d2be053dd004c963d7ed612296d7a574691accfdd26b2788126c94ad9d6311a0f77d9d4dc44d97cb169bd26f6d015
|
data/lib/paraxial/checker.rb
CHANGED
@@ -4,10 +4,13 @@ module Paraxial
|
|
4
4
|
@allows = { 'v4' => Patricia.new, 'v6' => Patricia.new(:AF_INET6) }
|
5
5
|
@bans = { 'v4' => Patricia.new, 'v6' => Patricia.new(:AF_INET6) }
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
|
8
|
+
if Paraxial::Helpers.get_api_key
|
9
|
+
@thread = Thread.new do
|
10
|
+
loop do
|
11
|
+
get_abr
|
12
|
+
sleep(10)
|
13
|
+
end
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
@@ -15,11 +18,16 @@ module Paraxial
|
|
15
18
|
uri = URI.parse(Paraxial::Helpers.get_paraxial_url + '/api/abr')
|
16
19
|
headers = { 'Content-Type': 'application/json' }
|
17
20
|
|
18
|
-
body = { api_key:
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
body = { api_key: Paraxial::Helpers.get_api_key }
|
22
|
+
begin
|
23
|
+
r = Net::HTTP.post(uri, body.to_json, headers)
|
24
|
+
if r.code == '200'
|
25
|
+
put_abr(JSON.parse(r.body))
|
26
|
+
else
|
27
|
+
'ab_failed'
|
28
|
+
end
|
29
|
+
rescue StandardError => e
|
30
|
+
puts '[Paraxial] HTTP connection to backend failed, check configuration'
|
23
31
|
'ab_failed'
|
24
32
|
end
|
25
33
|
end
|
@@ -100,7 +108,7 @@ module Paraxial
|
|
100
108
|
uri = URI.parse(Paraxial::Helpers.get_ban_url)
|
101
109
|
headers = { 'Content-Type': 'application/json' }
|
102
110
|
|
103
|
-
body = { api_key:
|
111
|
+
body = { api_key: Paraxial::Helpers.get_api_key, ip_address: ip }
|
104
112
|
r = Net::HTTP.post(uri, body.to_json, headers)
|
105
113
|
if r.code == '200'
|
106
114
|
:ok
|
data/lib/paraxial/cli.rb
CHANGED
@@ -19,14 +19,16 @@ module Paraxial
|
|
19
19
|
def scan
|
20
20
|
puts '[Paraxial] Scan starting...'
|
21
21
|
if check_rubocop_configuration
|
22
|
-
puts '[Paraxial] .rubocop.yml
|
22
|
+
puts '[Paraxial] .rubocop.yml is valid.'
|
23
23
|
else
|
24
|
-
puts '[Paraxial] .rubocop.yml
|
25
|
-
puts '
|
26
|
-
|
24
|
+
puts '[Paraxial] .rubocop.yml is missing rubocop-erb. To scan embedded Ruby files for security problems, add:'
|
25
|
+
puts '.rubocop.yml'
|
26
|
+
puts 'require:'
|
27
|
+
puts '- rubocop-erb'
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
|
31
|
+
if Paraxial::Helpers.get_api_key.nil?
|
30
32
|
puts '[Paraxial] Environment variable PARAXIAL_API_KEY not found'
|
31
33
|
else
|
32
34
|
github_app = options[:github_app]
|
@@ -36,7 +38,7 @@ module Paraxial
|
|
36
38
|
pr_number = options[:pr_number]
|
37
39
|
|
38
40
|
cops = 'Paraxial,Security/Eval,Security/IoMethods,Security/JSONLoad,Security/MarshalLoad,Security/Open,Security/YAMLLoad'
|
39
|
-
rubocop = `rubocop --only #{cops} --format json`
|
41
|
+
rubocop = `rubocop --require paraxial --only #{cops} --disable-pending-cops --format json`
|
40
42
|
lockfile = File.read('./Gemfile.lock')
|
41
43
|
api_key = ENV['PARAXIAL_API_KEY']
|
42
44
|
uri = URI.parse(Paraxial::Helpers.get_paraxial_url + '/api/ruby_scan')
|
@@ -47,7 +49,7 @@ module Paraxial
|
|
47
49
|
m = JSON.parse(response.body)
|
48
50
|
findings = m['ok']['findings']
|
49
51
|
puts
|
50
|
-
puts "[Paraxial] Scan count #{findings.length}"
|
52
|
+
puts "[Paraxial] Scan count: #{findings.length}"
|
51
53
|
puts
|
52
54
|
findings.each do |finding|
|
53
55
|
puts finding
|
@@ -107,7 +109,7 @@ module Paraxial
|
|
107
109
|
required_key = 'require'
|
108
110
|
|
109
111
|
if config.is_a?(Hash) && config[required_key].is_a?(Array)
|
110
|
-
config[required_key].include?('
|
112
|
+
config[required_key].include?('rubocop-erb')
|
111
113
|
else
|
112
114
|
false
|
113
115
|
end
|
data/lib/paraxial/helpers.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
unless Rails.env.test? || File.basename($0) == 'rake' || defined?(Rails::Generators)
|
2
|
+
module Marshal
|
3
|
+
class << self
|
4
|
+
alias_method :original_load, :load
|
5
|
+
|
6
|
+
def load(source, proc = nil)
|
7
|
+
exg = Paraxial.configuration.exploit_guard
|
8
|
+
if [:monitor, :block].include?(exg)
|
9
|
+
if source.is_a?(String) && source.match?(/ActionView|Net::BufferedIO|ERB|ActiveSupport/)
|
10
|
+
puts "[Paraxial] Exploit Guard triggered, malicious input to Marshal.load"
|
11
|
+
puts source
|
12
|
+
|
13
|
+
m = {
|
14
|
+
"api_key" => Paraxial::Helpers.get_api_key,
|
15
|
+
"mode" => exg,
|
16
|
+
"message" => "Marshal.load exploit behavior detected: #{Base64.encode64(source)}"
|
17
|
+
}
|
18
|
+
headers = { 'Content-Type': 'application/json' }
|
19
|
+
uri = URI.parse(Paraxial::Helpers.get_exploit_url)
|
20
|
+
Thread.new do
|
21
|
+
Net::HTTP.post(uri, m.to_json, headers)
|
22
|
+
end
|
23
|
+
if exg == :monitor
|
24
|
+
original_load(source, proc)
|
25
|
+
else
|
26
|
+
:block
|
27
|
+
end
|
28
|
+
else
|
29
|
+
original_load(source, proc)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
original_load(source, proc)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -8,16 +8,19 @@ Bundler.setup
|
|
8
8
|
|
9
9
|
unless Rails.env.test? || File.basename($0) == 'rake' || defined?(Rails::Generators)
|
10
10
|
Rails.application.config.to_prepare do
|
11
|
-
puts '[Paraxial]
|
12
|
-
api_key =
|
11
|
+
puts '[Paraxial] Agent starting...'
|
12
|
+
api_key = Paraxial::Helpers.get_api_key
|
13
13
|
|
14
14
|
if api_key.nil?
|
15
|
-
puts '[Paraxial]
|
15
|
+
puts '[Paraxial] PARAXIAL_API_KEY key not set, agent not started'
|
16
16
|
elsif Rails.env.test?
|
17
|
-
puts '[Paraxial]
|
17
|
+
puts '[Paraxial] Test environment detected, agent not started'
|
18
18
|
else
|
19
19
|
begin
|
20
|
-
puts '[Paraxial]
|
20
|
+
puts '[Paraxial] API key detected, agent starting'
|
21
|
+
|
22
|
+
Paraxial.check_exploit_guard
|
23
|
+
|
21
24
|
deps_and_licenses = []
|
22
25
|
Bundler.load.specs.each do |spec|
|
23
26
|
# Print the gem name and license
|
@@ -30,7 +33,7 @@ unless Rails.env.test? || File.basename($0) == 'rake' || defined?(Rails::Generat
|
|
30
33
|
uri = URI.parse(Paraxial::Helpers.get_paraxial_url + '/api/ruby_app_lic')
|
31
34
|
headers = { 'Content-Type': 'application/json' }
|
32
35
|
|
33
|
-
body = { app_lic: deps_and_licenses, api_key
|
36
|
+
body = { app_lic: deps_and_licenses, api_key: api_key, timestamp: Paraxial.get_timestamp }
|
34
37
|
cloud_uri = URI.parse(Paraxial::Helpers.get_paraxial_url + '/api/cloud_ip_list')
|
35
38
|
response = Net::HTTP.get(cloud_uri)
|
36
39
|
|
data/lib/paraxial/version.rb
CHANGED
data/lib/paraxial.rb
CHANGED
@@ -8,11 +8,16 @@ require_relative 'rubocop/cop/paraxial/system'
|
|
8
8
|
require_relative 'rubocop/cop/paraxial/send'
|
9
9
|
require_relative 'rubocop/cop/paraxial/constantize'
|
10
10
|
require_relative 'rubocop/cop/paraxial/html_safe'
|
11
|
+
require_relative 'rubocop/cop/paraxial/raw'
|
11
12
|
require_relative 'rubocop/cop/paraxial/sql'
|
12
13
|
require_relative 'paraxial/version'
|
13
14
|
require_relative 'paraxial/cli'
|
14
15
|
|
15
16
|
module Paraxial
|
17
|
+
class << self
|
18
|
+
attr_accessor :configuration
|
19
|
+
end
|
20
|
+
|
16
21
|
class Error < StandardError; end
|
17
22
|
# Your code goes here...
|
18
23
|
|
@@ -40,7 +45,11 @@ module Paraxial
|
|
40
45
|
end
|
41
46
|
|
42
47
|
def self.cloud_ip?(ip)
|
43
|
-
|
48
|
+
if ip.include?('.')
|
49
|
+
!!PARAXIAL_IPV4.search_best(ip)
|
50
|
+
else
|
51
|
+
!!PARAXIAL_IPV6.search_best(ip)
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
def self.ban_ip(ip)
|
@@ -66,4 +75,35 @@ module Paraxial
|
|
66
75
|
cleaned_string
|
67
76
|
end
|
68
77
|
end
|
78
|
+
|
79
|
+
def self.configure
|
80
|
+
self.configuration ||= Configuration.new
|
81
|
+
yield(configuration) if block_given?
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.check_exploit_guard
|
85
|
+
if configuration.nil?
|
86
|
+
puts "[Paraxial] Exploit Guard, no config exists, will not run"
|
87
|
+
return
|
88
|
+
end
|
89
|
+
|
90
|
+
case configuration.exploit_guard
|
91
|
+
when :monitor
|
92
|
+
puts "[Paraxial] Exploit Guard, running in monitor mode"
|
93
|
+
when :block
|
94
|
+
puts "[Paraxial] Exploit Guard, running in block mode"
|
95
|
+
when nil
|
96
|
+
puts "[Paraxial] Exploit Guard, not configured, will not run"
|
97
|
+
else
|
98
|
+
puts "[Paraxial] Exploit Guard, bad value"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Configuration
|
103
|
+
attr_accessor :exploit_guard
|
104
|
+
|
105
|
+
def initialize
|
106
|
+
@exploit_guard = nil
|
107
|
+
end
|
108
|
+
end
|
69
109
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RuboCop
|
2
|
+
module Cop
|
3
|
+
module Paraxial
|
4
|
+
class Raw < Base
|
5
|
+
MSG = '`raw` leads to XSS when called on user input'
|
6
|
+
|
7
|
+
def on_send(node)
|
8
|
+
method_name = node.method_name
|
9
|
+
return unless send_methods.include?(method_name)
|
10
|
+
|
11
|
+
add_offense(node, message: format(MSG, method: method_name))
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def send_methods
|
17
|
+
[:raw]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paraxial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Lubas
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-erb
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description:
|
70
84
|
email:
|
71
85
|
- michael@paraxial.io
|
@@ -84,11 +98,13 @@ files:
|
|
84
98
|
- lib/paraxial/cli.rb
|
85
99
|
- lib/paraxial/engine.rb
|
86
100
|
- lib/paraxial/helpers.rb
|
101
|
+
- lib/paraxial/initializers/marshal_patch.rb
|
87
102
|
- lib/paraxial/initializers/startup.rb
|
88
103
|
- lib/paraxial/version.rb
|
89
104
|
- lib/rubocop/cop/paraxial/constantize.rb
|
90
105
|
- lib/rubocop/cop/paraxial/csrf.rb
|
91
106
|
- lib/rubocop/cop/paraxial/html_safe.rb
|
107
|
+
- lib/rubocop/cop/paraxial/raw.rb
|
92
108
|
- lib/rubocop/cop/paraxial/send.rb
|
93
109
|
- lib/rubocop/cop/paraxial/sql.rb
|
94
110
|
- lib/rubocop/cop/paraxial/system.rb
|