paraxial 0.4.0 → 0.6.0

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