pluginscan 0.9.0

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