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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce7c75f780f9b356d4a15b4fb834bb6f064a8f5a39ead6e629a4f42ff2768010
4
- data.tar.gz: 929b701d0e47c7a12b1654c3426e515b37824f591b7a65b2c9a22630c72bc8cc
3
+ metadata.gz: 2ef49572c0555fdaea4bc13d94f4faa2d771a9919ee54304d832b5b97306cc09
4
+ data.tar.gz: 3bd3f48e2517d1c309e8c57ec8814a6bf9077506c461904c5f38f1ecc7e35dd3
5
5
  SHA512:
6
- metadata.gz: b1d9decea112098e9c71cf36d071fe1fbe86028ac23b34d4b9a704771d7a007a42f56abbaea51dc65825067e0ac5d029781b7c344c82a3cd339716908f6d8451
7
- data.tar.gz: 54bff15c7c351b7f3e74eae787d2858f12e4ded57be06cb3f5872147cdccae90819396837fa60e5ddeda6fff758eddeef0868fed4d02748c3873282c6c59306e
6
+ metadata.gz: 6ed1f565c95cffdc6e8940d2c92c1cee7c7cd6157fe5da9f304746a65c1687ca74141483add2ca13616cfe82371a27b396ae4fcb178dffb80cac014ace5ac152
7
+ data.tar.gz: aa3ab3d9ff75cd0ff804a859eebd847ca60d2be053dd004c963d7ed612296d7a574691accfdd26b2788126c94ad9d6311a0f77d9d4dc44d97cb169bd26f6d015
@@ -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
- @thread = Thread.new do
8
- loop do
9
- get_abr
10
- sleep(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: ENV['PARAXIAL_API_KEY'] }
19
- r = Net::HTTP.post(uri, body.to_json, headers)
20
- if r.code == '200'
21
- put_abr(JSON.parse(r.body))
22
- else
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: ENV['PARAXIAL_API_KEY'], ip_address: ip }
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 contains the required paraxial configuration.'
22
+ puts '[Paraxial] .rubocop.yml is valid.'
23
23
  else
24
- puts '[Paraxial] .rubocop.yml does not contain the required paraxial configuration.'
25
- puts '[Paraxial] How to configure: TODO_URL'
26
- exit
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
- if ENV['PARAXIAL_API_KEY'].nil?
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?('paraxial')
112
+ config[required_key].include?('rubocop-erb')
111
113
  else
112
114
  false
113
115
  end
@@ -7,5 +7,13 @@ module Paraxial
7
7
  def self.get_ban_url
8
8
  get_paraxial_url + '/api/ban_ip'
9
9
  end
10
+
11
+ def self.get_exploit_url
12
+ get_paraxial_url + '/api/exploit'
13
+ end
14
+
15
+ def self.get_api_key
16
+ @paraxial_api_key ||= ENV['PARAXIAL_API_KEY']
17
+ end
10
18
  end
11
19
  end
@@ -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] Init start'
12
- api_key = ENV['PARAXIAL_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] Init PARAXIAL_API_KEY key not set, agent not started'
15
+ puts '[Paraxial] PARAXIAL_API_KEY key not set, agent not started'
16
16
  elsif Rails.env.test?
17
- puts '[Paraxial] Init Test environment detected, agent not started'
17
+ puts '[Paraxial] Test environment detected, agent not started'
18
18
  else
19
19
  begin
20
- puts '[Paraxial] Init config valid, agent starting'
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:, timestamp: Paraxial.get_timestamp }
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Paraxial
4
- VERSION = '0.4.0'
4
+ VERSION = '0.6.0'
5
5
  end
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
- !!(PARAXIAL_IPV4.search_best(ip) or PARAXIAL_IPV6.search_best(ip))
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.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-08-22 00:00:00.000000000 Z
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