pluginscan 0.9.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.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +46 -0
  6. data/.rubocop_todo.yml +36 -0
  7. data/CHANGELOG.md +89 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +90 -0
  10. data/README.md +56 -0
  11. data/Rakefile +2 -0
  12. data/TODO.md +8 -0
  13. data/bin/pluginscan +53 -0
  14. data/lib/file_creator.rb +18 -0
  15. data/lib/pluginscan.rb +69 -0
  16. data/lib/pluginscan/error.rb +9 -0
  17. data/lib/pluginscan/error_printer.rb +17 -0
  18. data/lib/pluginscan/file_finder.rb +42 -0
  19. data/lib/pluginscan/printer.rb +14 -0
  20. data/lib/pluginscan/reports/cloc_report.rb +27 -0
  21. data/lib/pluginscan/reports/cloc_report/cloc.rb +21 -0
  22. data/lib/pluginscan/reports/cloc_report/cloc_printer.rb +42 -0
  23. data/lib/pluginscan/reports/cloc_report/cloc_scanner.rb +41 -0
  24. data/lib/pluginscan/reports/cloc_report/system_cloc.rb +33 -0
  25. data/lib/pluginscan/reports/issues_report.rb +24 -0
  26. data/lib/pluginscan/reports/issues_report/error_list_printer.rb +99 -0
  27. data/lib/pluginscan/reports/issues_report/issue_checks.rb +382 -0
  28. data/lib/pluginscan/reports/issues_report/issue_checks/check.rb +55 -0
  29. data/lib/pluginscan/reports/issues_report/issue_checks/comment_checker.rb +13 -0
  30. data/lib/pluginscan/reports/issues_report/issue_checks/function_check.rb +32 -0
  31. data/lib/pluginscan/reports/issues_report/issue_checks/variable_check.rb +14 -0
  32. data/lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb +112 -0
  33. data/lib/pluginscan/reports/issues_report/issues_models/check_findings.rb +29 -0
  34. data/lib/pluginscan/reports/issues_report/issues_models/issues.rb +31 -0
  35. data/lib/pluginscan/reports/issues_report/issues_printer.rb +34 -0
  36. data/lib/pluginscan/reports/issues_report/issues_printer/check_findings_printer.rb +37 -0
  37. data/lib/pluginscan/reports/issues_report/issues_printer/file_issues_printer.rb +36 -0
  38. data/lib/pluginscan/reports/issues_report/issues_printer/finding_printer.rb +38 -0
  39. data/lib/pluginscan/reports/issues_report/issues_printer_factory.rb +19 -0
  40. data/lib/pluginscan/reports/issues_report/issues_scanner.rb +49 -0
  41. data/lib/pluginscan/reports/issues_report/issues_scanner/file_issues_scanner.rb +39 -0
  42. data/lib/pluginscan/reports/issues_report/issues_scanner/line_issues_scanner.rb +15 -0
  43. data/lib/pluginscan/reports/issues_report/issues_scanner/utf8_checker.rb +14 -0
  44. data/lib/pluginscan/reports/sloccount_report.rb +26 -0
  45. data/lib/pluginscan/reports/sloccount_report/sloccount.rb +19 -0
  46. data/lib/pluginscan/reports/sloccount_report/sloccount_printer.rb +22 -0
  47. data/lib/pluginscan/reports/sloccount_report/sloccount_scanner.rb +86 -0
  48. data/lib/pluginscan/reports/vulnerability_report.rb +28 -0
  49. data/lib/pluginscan/reports/vulnerability_report/advisories_api.rb +23 -0
  50. data/lib/pluginscan/reports/vulnerability_report/vulnerabilities_printer.rb +55 -0
  51. data/lib/pluginscan/reports/vulnerability_report/vulnerability_scanner.rb +17 -0
  52. data/lib/pluginscan/reports/vulnerability_report/wp_vuln_db_api.rb +77 -0
  53. data/lib/pluginscan/version.rb +3 -0
  54. data/pluginscan.gemspec +31 -0
  55. data/spec/acceptance/cloc_spec.rb +54 -0
  56. data/spec/acceptance/create_error_list_file_spec.rb +29 -0
  57. data/spec/acceptance/issues_spec.rb +197 -0
  58. data/spec/acceptance/pluginscan_spec.rb +18 -0
  59. data/spec/acceptance/sloccount_spec.rb +39 -0
  60. data/spec/acceptance/vulnerabilities_spec.rb +57 -0
  61. data/spec/acceptance_spec_helper.rb +10 -0
  62. data/spec/checks_examples_spec.rb +352 -0
  63. data/spec/file_creator_spec.rb +51 -0
  64. data/spec/pluginscan/cloc_scanner/cloc_scanner_spec.rb +64 -0
  65. data/spec/pluginscan/cloc_scanner/cloc_spec.rb +30 -0
  66. data/spec/pluginscan/file_finder_spec.rb +91 -0
  67. data/spec/pluginscan/issues_scanner/check_findings_spec.rb +22 -0
  68. data/spec/pluginscan/issues_scanner/error_list_printer_ignores_spec.rb +35 -0
  69. data/spec/pluginscan/issues_scanner/error_list_printer_spec.rb +42 -0
  70. data/spec/pluginscan/issues_scanner/file_issues_scanner_spec.rb +25 -0
  71. data/spec/pluginscan/issues_scanner/issues_printer_factory_spec.rb +9 -0
  72. data/spec/pluginscan/issues_scanner/issues_spec.rb +55 -0
  73. data/spec/pluginscan/issues_scanner/variable_check_spec.rb +13 -0
  74. data/spec/pluginscan/issues_scanner/variable_safety_checker_spec.rb +81 -0
  75. data/spec/pluginscan/issues_scanner_spec.rb +21 -0
  76. data/spec/pluginscan/sloccount_scanner/sloccount_scanner_spec.rb +95 -0
  77. data/spec/pluginscan/sloccount_scanner/sloccount_spec.rb +72 -0
  78. data/spec/pluginscan/vulnerability_scanner_spec.rb +96 -0
  79. data/spec/process_spec_helper.rb +6 -0
  80. data/spec/spec_helper.rb +70 -0
  81. data/spec/support/acceptance_helpers.rb +68 -0
  82. data/spec/support/file_helpers.rb +35 -0
  83. data/spec/support/heredoc_helper.rb +7 -0
  84. data/spec/support/process_helpers.rb +25 -0
  85. data/spec/support/shared_examples_for_issue_checks.rb +31 -0
  86. data/spec/support/vcr_helper.rb +6 -0
  87. data/vcr_cassettes/wpvulndb/relevanssi.yml +78 -0
  88. metadata +342 -0
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Pluginscan::VariableSafetyChecker do
4
+ describe ".all_safe" do
5
+ it "returns true when two superglobals are both safe" do
6
+ variable = "$_POST"
7
+ content = "if ( isset( $_POST['action'] ) && $_POST['action'] == 'enter-key' ) \{"
8
+ expect(described_class.new.all_safe?(variable, content)).to eq true
9
+ end
10
+
11
+ it "returns false when, of two superglobals only one is safe" do
12
+ variable = "$_POST"
13
+ content = "$submitted = isset( $_POST[$tagname] ) ? $_POST[$tagname] : '';"
14
+ expect(described_class.new.all_safe?(variable, content)).to eq false
15
+ end
16
+ end
17
+
18
+ describe ".match_count" do
19
+ it "returns 1 when there is 1 occurrence" do
20
+ expect(described_class.new.match_count("$_POST", "$contact_form->set_title( $_POST['wpcf7-title'] );")).to eq 1
21
+ end
22
+ it "returns 2 when there are 2 occurrences" do
23
+ expect(described_class.new.match_count("$_POST", "$submitted = isset( $_POST[$tagname] ) ? $_POST[$tagname] : '';")).to eq 2
24
+ end
25
+ end
26
+
27
+ describe ".wrapped_in_function_count - isset" do
28
+ def count(content)
29
+ described_class.new.wrapped_in_function_count('isset', variable, content)
30
+ end
31
+
32
+ context "when a single superglobal is wrapped in an 'isset'" do
33
+ let(:variable) { "$_GET" }
34
+ specify { expect(count("if ( isset( $_GET['action'] ) )")).to eq 1 }
35
+ specify { expect(count("if ( isset ( $_GET['action'] ) )")).to eq 1 }
36
+ specify { expect(count("if ( isset($_GET['action']))")).to eq 1 }
37
+ end
38
+
39
+ context 'when one superglobal is wrapped in isset and another is not' do
40
+ let(:variable) { "$_POST" }
41
+ specify { expect(count("$submitted = isset( $_POST[$tagname] ) ? $_POST[$tagname] : '';")).to eq 1 }
42
+ end
43
+ end
44
+
45
+ describe ".wrapped_in_function_count - 'empty'" do
46
+ def count(content)
47
+ described_class.new.wrapped_in_function_count('empty', "$_POST", content)
48
+ end
49
+
50
+ context "when a single superglobal is wrapped in an 'empty'" do
51
+ specify { expect(count("if ( ! empty( $_POST['post_ID'] ))")).to eq 1 }
52
+ specify { expect(count("if ( ! empty ( $_POST['post_ID'] ) )")).to eq 1 }
53
+ specify { expect(count("if ( ! empty($_POST['post_ID']))")).to eq 1 }
54
+ end
55
+
56
+ context "when two superglobals are wrapped in an 'empty'" do
57
+ specify { expect(count("if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) \{")).to eq 2 }
58
+ end
59
+ end
60
+
61
+ describe ".used_in_infix_check_count - ==" do
62
+ def count(content)
63
+ described_class.new.used_in_infix_check_count('==', variable, content)
64
+ end
65
+
66
+ context "when a single superglobal is used in an equality check" do
67
+ let(:variable) { "$_SERVER" }
68
+ specify { expect(count("if ( 'POST'== $_SERVER['REQUEST_METHOD'] ) \{")).to eq 1 }
69
+ specify { expect(count("if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) \{")).to eq 1 }
70
+ specify { expect(count("if ( 'POST' ==$_SERVER[ 'REQUEST_METHOD'] ) \{")).to eq 1 }
71
+ specify { expect(count("if ( 'POST'==$_SERVER['REQUEST_METHOD'] ) \{")).to eq 1 }
72
+ specify { expect(count("return $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] == 'XMLHttpRequest';")).to be_truthy }
73
+ specify { expect(count("return $_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest';")).to be_truthy }
74
+ end
75
+
76
+ context 'when one superglobal is used in an equality check and another is not' do
77
+ let(:variable) { "$_POST" }
78
+ specify { expect(count("if ( isset( $_POST['action'] ) && $_POST['action'] == 'enter-key' ) \{")).to eq 1 }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,21 @@
1
+ RSpec.describe Pluginscan::FileScanner do
2
+ describe "#scan" do
3
+ subject(:scanner) { Pluginscan::FileScanner.new(double) }
4
+ let(:results) { scanner.scan(file_contents) }
5
+
6
+ context 'with a file which is invalid utf-8' do
7
+ let(:file_contents) { "\xc2" }
8
+ it "finds one result" do
9
+ expect(results.count).to eq 1
10
+ end
11
+ it "finds a result of invalid UTF-8" do
12
+ expect(results.first.check.name).to eq 'Encoding'
13
+ expect(results.first.check.message).to eq 'invalid UTF-8'
14
+ end
15
+ it "finds a result with no findings" do
16
+ expect(results.first.findings).to eq []
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'support/heredoc_helper'
3
+
4
+ RSpec.describe SLOCCountScanner, type: :process do
5
+ # For safety and speed: disable the system calls by default
6
+ before do
7
+ stub_const('SystemSLOCCount', double)
8
+ end
9
+
10
+ describe ".scan" do
11
+ it "returns a SLOCCount object when sloccount is successful" do
12
+ stub_dir_exists
13
+ system_sloccount = fake_system_sloccount(
14
+ result: "The thing worked. Your sloccount was lots",
15
+ process_status: successful_process_status
16
+ )
17
+ expect(SLOCCountScanner.new(system_sloccount).scan("my_directory")).to be_a(SLOCCount)
18
+ end
19
+
20
+ it "returns a null SLOCCount object when sloccount gives a zero sloc result" do
21
+ stub_dir_exists
22
+ system_sloccount = fake_system_sloccount(
23
+ result: ZERO_SLOCCOUNT_OUTPUT,
24
+ process_status: failed_process_status
25
+ )
26
+ expect(SLOCCountScanner.new(system_sloccount).scan("my_directory")).to be_a(NullSLOCCount)
27
+ end
28
+
29
+ # EXCEPTION HANDLING:
30
+ #####################
31
+
32
+ it "raises an error when no directory is passed" do
33
+ expect{ SLOCCountScanner.new(anything).scan(nil) }
34
+ .to raise_error SLOCCountScanner::ArgumentError
35
+ end
36
+
37
+ it "raises an error when the directory doesn't exist" do
38
+ system_sloccount = fake_system_sloccount(available: true)
39
+ expect{ SLOCCountScanner.new(system_sloccount).scan("my_directory") }
40
+ .to raise_error SLOCCountScanner::NoDirectory
41
+ end
42
+
43
+ it "raises an error when sloccount was not available" do
44
+ stub_dir_exists
45
+ system_sloccount = fake_system_sloccount(available: false)
46
+ expect{ SLOCCountScanner.new(system_sloccount).scan("my_directory") }
47
+ .to raise_error SLOCCountScanner::Unavailable
48
+ end
49
+
50
+ it 'raises an error when sloccount returns an unrecognised error' do
51
+ stub_dir_exists
52
+ system_sloccount = fake_system_sloccount(
53
+ result: "Some nonsense",
54
+ process_status: failed_process_status
55
+ )
56
+ expect{ SLOCCountScanner.new(system_sloccount).scan("my_directory") }
57
+ .to raise_error SLOCCountScanner::Exception
58
+ end
59
+
60
+ it 'raises an error when sloccount returns a `no input` error' do
61
+ stub_dir_exists
62
+ # In reality this should never happen because we check for this case
63
+ system_sloccount = fake_system_sloccount(
64
+ result: NO_INPUT_SLOCCOUNT_OUTPUT,
65
+ process_status: failed_process_status
66
+ )
67
+ expect{ SLOCCountScanner.new(system_sloccount).scan("my_directory") }
68
+ .to raise_error SLOCCountScanner::NoInput
69
+ end
70
+
71
+ def fake_system_sloccount(result: nil, process_status: successful_process_status, available: true)
72
+ instance_double('SystemSLOCCount').tap do |fake|
73
+ allow(fake).to receive(:call).and_return [result, process_status]
74
+ allow(fake).to receive(:available?).and_return(available)
75
+ end
76
+ end
77
+
78
+ def stub_dir_exists
79
+ allow(Dir).to receive(:exist?).and_return(true)
80
+ end
81
+
82
+ ZERO_SLOCCOUNT_OUTPUT = <<-EOS.heredoc_unindent
83
+ filelist for tmp
84
+ Categorizing files.
85
+ Computing results.
86
+
87
+
88
+ SLOC Directory SLOC-by-Language (Sorted)
89
+ 0 tmp (none)
90
+ SLOC total is zero, no further analysis performed.
91
+ EOS
92
+
93
+ NO_INPUT_SLOCCOUNT_OUTPUT = "Error: You must provide a directory or directories of source code.\n".freeze
94
+ end
95
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'support/heredoc_helper'
3
+
4
+ RSpec.describe NullSLOCCount do
5
+ subject(:null_sloccount) { NullSLOCCount.new }
6
+ describe ".total" do
7
+ subject { null_sloccount.total }
8
+ it { is_expected.to eq 0 }
9
+ end
10
+ end
11
+
12
+ RSpec.describe SLOCCount do
13
+ describe "#total" do
14
+ it "returns the total sloccount shown in the sloccount output file" do
15
+ sloccount = SLOCCount.new(SLOCCOUNT_OUTPUT_RUBY_785)
16
+ expect(sloccount.total).to eq 785
17
+ end
18
+ end
19
+
20
+ SLOCCOUNT_OUTPUT_RUBY_785 = <<-EOS.heredoc_unindent
21
+ Have a non-directory at the top, so creating directory top_dir
22
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./CHANGELOG.md to top_dir
23
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./Gemfile to top_dir
24
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./Gemfile.lock to top_dir
25
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./README.md to top_dir
26
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./TODO.md to top_dir
27
+ Creating filelist for bin
28
+ Creating filelist for coverage
29
+ Creating filelist for lib
30
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./pluginscan-0.1.1.gem to top_dir
31
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./pluginscan-0.1.2.gem to top_dir
32
+ Adding /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/./pluginscan.gemspec to top_dir
33
+ Creating filelist for spec
34
+ Creating filelist for tmp
35
+ Categorizing files.
36
+ WARNING! File /Users/dxwduncan/Dev/Ruby_and_rails/pluginscan/bin/pluginscan has unknown start: #!/usr/bin/env ruby
37
+ Finding a working MD5 command....
38
+ Found a working MD5 command.
39
+ Computing results.
40
+
41
+
42
+ SLOC Directory SLOC-by-Language (Sorted)
43
+ 412 spec ruby=412
44
+ 373 lib ruby=373
45
+ 0 bin (none)
46
+ 0 coverage (none)
47
+ 0 tmp (none)
48
+ 0 top_dir (none)
49
+
50
+
51
+ Totals grouped by language (dominant language first):
52
+ ruby: 785 (100.00%)
53
+
54
+
55
+
56
+
57
+ Total Physical Source Lines of Code (SLOC) = 785
58
+ Development Effort Estimate, Person-Years (Person-Months) = 0.16 (1.86)
59
+ (Basic COCOMO model, Person-Months = 2.4 * (KSLOC**1.05))
60
+ Schedule Estimate, Years (Months) = 0.26 (3.17)
61
+ (Basic COCOMO model, Months = 2.5 * (person-months**0.38))
62
+ Estimated Average Number of Developers (Effort/Schedule) = 0.59
63
+ Total Estimated Cost to Develop = $ 20,953
64
+ (average salary = $56,286/year, overhead = 2.40).
65
+ SLOCCount, Copyright (C) 2001-2004 David A. Wheeler
66
+ SLOCCount is Open Source Software/Free Software, licensed under the GNU GPL.
67
+ SLOCCount comes with ABSOLUTELY NO WARRANTY, and you are welcome to
68
+ redistribute it under certain conditions as specified by the GNU GPL license;
69
+ see the documentation for details.
70
+ Please credit this data as "generated using David A. Wheeler's 'SLOCCount'."
71
+ EOS
72
+ end
@@ -0,0 +1,96 @@
1
+ RSpec.describe Pluginscan::VulnerabilityScanner do
2
+ describe "#scan" do
3
+ subject(:scanner) { Pluginscan::VulnerabilityScanner.new }
4
+
5
+ it "raises an error if the result didn't include the plugin slug" do
6
+ stub_vuln_api_success('another_plugin' => { 'vulnerabilities' => [] })
7
+ expect{ scanner.scan('my_plugin') }
8
+ .to raise_error(Pluginscan::WPVulnDB::UnexpectedJSONError)
9
+ end
10
+
11
+ it "raises an error if a list of vulnerabilities couldn't be found" do
12
+ stub_vuln_api_success('my_plugin' => {})
13
+ expect{ scanner.scan('my_plugin') }
14
+ .to raise_error(Pluginscan::WPVulnDB::UnexpectedJSONError)
15
+ end
16
+
17
+ it "returns an empty array if the response was 'not found'" do
18
+ stub_vuln_api_response_not_found
19
+ expect(scanner.scan('my_plugin')).to eq []
20
+ end
21
+
22
+ it "raises an error if we got blocked" do
23
+ stub_vuln_api_response_blocked
24
+ expect{ scanner.scan('my_plugin') }
25
+ .to raise_error(Pluginscan::WPVulnDB::AccessDeniedError)
26
+ end
27
+
28
+ it "raises an error if the code wasn't 200" do
29
+ stub_vuln_api_response(status: 503, body: 'Something went wrong')
30
+ expect{ scanner.scan('my_plugin') }
31
+ .to raise_error(Pluginscan::WPVulnDB::APIError)
32
+ end
33
+
34
+ it "raises an error if the connection failed with a socket error" do
35
+ allow(HTTParty).to receive(:get).and_raise(SocketError, "Failed to open TCP connection to wpvulndb.com:443 (getaddrinfo: nodename nor servname provided, or not known)")
36
+ expect{ scanner.scan('my_plugin') }
37
+ .to raise_error(Pluginscan::AdvisoriesAPI::ConnectionError)
38
+ end
39
+
40
+ it "raises an error if the connection failed with a timeout" do
41
+ allow(HTTParty).to receive(:get).and_raise(Net::OpenTimeout, "execution expired (Net::OpenTimeout)")
42
+ expect{ scanner.scan('my_plugin') }
43
+ .to raise_error(Pluginscan::AdvisoriesAPI::ConnectionError)
44
+ end
45
+
46
+ it "returns an array of hashes if results were found" do
47
+ vulnerabilities = [
48
+ {
49
+ 'id' => 6425,
50
+ 'title' => "Relevanssi 3.2 - Unspecified SQL Injection",
51
+ 'created_at' => "2014-08-01T10:58:47.000Z",
52
+ 'fixed_in' => "3.3",
53
+ },
54
+ {
55
+ 'id' => 6426,
56
+ 'title' => "Relevanssi 2.7.2 - Stored XSS Vulnerability",
57
+ 'created_at' => "2014-08-23T10:58:47.000Z",
58
+ 'fixed_in' => "2.7.3",
59
+ },
60
+ ]
61
+ stub_vuln_api_success('my_plugin' => { 'vulnerabilities' => vulnerabilities })
62
+ results = scanner.scan('my_plugin')
63
+ expect(results.count).to eq 2
64
+
65
+ expect(results.first.title).to eq "Relevanssi 3.2 - Unspecified SQL Injection"
66
+ expect(results.first.date).to eq Date.new(2014, 8, 1)
67
+ expect(results.first.fixed_in).to eq "3.3"
68
+ expect(results.first.url).to eq "https://wpvulndb.com/vulnerabilities/6425"
69
+
70
+ expect(results.last.title).to eq "Relevanssi 2.7.2 - Stored XSS Vulnerability"
71
+ expect(results.last.date).to eq Date.new(2014, 8, 23)
72
+ expect(results.last.fixed_in).to eq "2.7.3"
73
+ expect(results.last.url).to eq "https://wpvulndb.com/vulnerabilities/6426"
74
+ end
75
+
76
+ def stub_vuln_api_success(body)
77
+ json_header = { 'Content-Type' => 'application/json; charset=utf-8' }
78
+ stub_vuln_api_response(status: 200, body: body.to_json, headers: json_header)
79
+ end
80
+
81
+ def stub_vuln_api_response_not_found
82
+ stub_vuln_api_response(status: 404, body: "The page you were looking for doesn't exist (404).")
83
+ end
84
+
85
+ def stub_vuln_api_response_blocked
86
+ blocked_page = "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Access denied</title>\n <link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" />\n</head>\n\n<body>\n <div class=\"center\">\n <h1>Access denied</h1>\n <p>Your IP was blocked because of suspicious acitivity.</p>\n <p>If you think your IP should not be blocked, please contact us at team [at] wpvulndb [.] com</p>\n </div>\n</body>\n</html>\n"
87
+ stub_vuln_api_response(status: 403, body: blocked_page)
88
+ end
89
+
90
+ def stub_vuln_api_response(status: 200, body: '', headers: {})
91
+ stub_request(:get, 'https://wpvulndb.com/api/v2/plugins/my_plugin')
92
+ .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => 'Ruby' })
93
+ .to_return(status: status, body: body, headers: headers)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'support/process_helpers'
3
+
4
+ RSpec.configure do |config|
5
+ config.include ProcessHelpers, type: :process
6
+ end
@@ -0,0 +1,70 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ require 'pluginscan'
7
+ require 'webmock/rspec'
8
+
9
+ RSpec.configure do |config|
10
+ config.expect_with :rspec do |expectations|
11
+ # This option will default to `true` in RSpec 4. It makes the `description`
12
+ # and `failure_message` of custom matchers include text for helper methods
13
+ # defined using `chain`, e.g.:
14
+ # be_bigger_than(2).and_smaller_than(4).description
15
+ # # => "be bigger than 2 and smaller than 4"
16
+ # ...rather than:
17
+ # # => "be bigger than 2"
18
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
19
+ end
20
+
21
+ config.mock_with :rspec do |mocks|
22
+ # Prevents you from mocking or stubbing a method that does not exist on
23
+ # a real object. This is generally recommended, and will default to
24
+ # `true` in RSpec 4.
25
+ mocks.verify_partial_doubles = true
26
+ end
27
+
28
+ config.filter_run :focus
29
+ config.run_all_when_everything_filtered = true
30
+
31
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
32
+ # For more details, see:
33
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
34
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
35
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
36
+ config.disable_monkey_patching!
37
+
38
+ # This setting enables warnings. It's recommended, but in some cases may
39
+ # be too noisy due to issues in dependencies.
40
+ config.warnings = true
41
+
42
+ # Many RSpec users commonly either run the entire suite or an individual
43
+ # file, and it's useful to allow more verbose output when running an
44
+ # individual spec file.
45
+ if config.files_to_run.one?
46
+ # Use the documentation formatter for detailed output,
47
+ # unless a formatter has already been configured
48
+ # (e.g. via a command-line flag).
49
+ config.default_formatter = 'doc'
50
+ end
51
+
52
+ config.example_status_persistence_file_path = 'failures.txt'
53
+
54
+ # Print the 10 slowest examples and example groups at the
55
+ # end of the spec run, to help surface which specs are running
56
+ # particularly slow.
57
+ # config.profile_examples = 10
58
+
59
+ # Run specs in random order to surface order dependencies. If you find an
60
+ # order dependency and want to debug it, you can fix the order by providing
61
+ # the seed, which is printed after each run.
62
+ # --seed 1234
63
+ config.order = :random
64
+
65
+ # Seed global randomization in this process using the `--seed` CLI option.
66
+ # Setting this allows you to use `--seed` to deterministically reproduce
67
+ # test failures related to randomization by passing the same `--seed` value
68
+ # as the one that triggered the failure.
69
+ # Kernel.srand config.seed
70
+ end