require 'acceptance_spec_helper' RSpec.describe Pluginscan::Scanner do before do stub_vuln_check end describe '.scan' do let(:output) { StringIO.new } describe "Issue Report", type: :file do subject(:scanner) { Pluginscan::Scanner.new(sloccount: false, cloc: false, output: output) } context 'when there are no files in the directory' do before :all do setup_tempdir 'tmp' end it "returns true" do expect(scanner.scan("tmp")).to be true end it "says it found nothing" do scanner.scan "tmp" expect(output.string).to match(/found 0 things/) end end context "when there are no php files" do before(:all) do setup_tempdir 'tmp' add_non_php_file 'tmp' end it "returns true" do expect(scanner.scan("tmp")).to be true end it "says it found nothing" do scanner.scan "tmp" expect(output.string).to match(/found 0 things/) end end context 'when there are php files with issues' do let(:scanner_hide_ignores) { Pluginscan::Scanner.new(sloccount: false, cloc: false, output: output, hide_ignores: true) } before(:each) do setup_tempdir 'tmp' @file_name = add_php_file 'tmp', " eval('delete all the things')\n global $wpdb;" end it 'returns true' do expect(scanner.scan("tmp")).to be true end # TODO: split this out into specific specs OR (better) find a way to test # all the cases at a lower level it 'shows the filename in the output' do all_ignored_file_name = add_php_file 'tmp', " global $wpdb;" scanner.scan "tmp" expect(output.string).to match(/#{@file_name}/) expect(output.string).to match(/#{all_ignored_file_name}/) end it 'shows the filename in the output when ignores are hidden' do scanner_hide_ignores.scan "tmp" expect(output.string).to match(/#{@file_name}/) end it "doesn't show the filename in the output if all lines are ignored and 'show ignores' is false" do all_ignored_file_name = add_php_file 'tmp', " global $wpdb;" scanner_hide_ignores.scan "tmp" expect(output.string).to_not match(/#{all_ignored_file_name}/) end it 'shows the issue type in the output' do scanner.scan "tmp" expect(output.string).to match(/PHP code generation/) expect(output.string).to match(/Database access/) end it "doesn't show issue types for empty groups (where all checks are ignored) if 'show ignores' is false" do scanner_hide_ignores.scan "tmp" expect(output.string).to_not match(/Database access/) end it 'shows the problematic line in the output' do problematic_line = /1: #{coloured_cyan('eval')}\('delete all the things'\)/ scanner.scan "tmp" expect(output.string).to match(problematic_line) end it "doesn't show files which have no issues" do no_issues_file_name = add_php_file 'tmp', "foo bar baz" scanner.scan "tmp" expect(output.string).to_not match(/#{no_issues_file_name}/) end it "shows lines which are ignored" do i_symbol = coloured_red(Regexp.escape('[I]')) wpdb = coloured_cyan(Regexp.escape('$wpdb')) scanner.scan "tmp" expect(output.string).to match(/#{i_symbol}\s+2: global #{wpdb};/) end it "hides checks where all lines are ignored if 'show ignores' is false" do wpdb = coloured_cyan(Regexp.escape('$wpdb')) scanner_hide_ignores.scan "tmp" expect(output.string).to_not match(/global #{wpdb};/) end it "hides lines which are ignored where other lines in the same check are NOT ignored if 'show ignores' is false" do add_php_file 'tmp', "global $wpdb; \n $wpdb->query($evil);" wpdb = coloured_cyan(Regexp.escape('$wpdb')) scanner_hide_ignores.scan "tmp" expect(output.string).to_not match(/global #{wpdb};/) end end it "shows non-UTF-8 encoding as a finding" do add_php_file 'tmp', "\xC2" scanner.scan "tmp" expect(output.string).to match(/invalid UTF-8/) end context 'when there are php files nested within folders' do it "scans those files" do setup_tempdir 'tmp' add_directory 'tmp', 'foo' add_php_file 'tmp/foo' add_directory 'tmp', 'foo/bar' add_php_file 'tmp/foo/bar' scanner.scan "tmp" expect(output.string).to match(/Scanned 2 out of 2 files/) end end describe 'counting:' do context do before :all do setup_tempdir 'tmp' add_php_file 'tmp' end it 'counts php files' do scanner.scan "tmp" expect(output.string).to match(/out of 1 files/) end it 'scans php files' do scanner.scan "tmp" expect(output.string).to match(/Scanned 1/) end end context do before :all do setup_tempdir 'tmp' add_directory 'tmp' add_php_file 'tmp' end it 'ignores directories when counting' do scanner.scan "tmp" expect(output.string).to match(/out of 1 files/) end it 'ignores directories when scanning' do scanner.scan "tmp" expect(output.string).to match(/Scanned 1/) end end it "returns the total number of things found" do setup_tempdir 'tmp' add_php_file 'tmp', " eval('foo')\n$_POST" add_php_file 'tmp', '$wpdb->query( "DROP TABLE' scanner.scan "tmp" expect(output.string).to match(/found 3 things:/) end it 'displays a full message about counts' do setup_tempdir 'tmp' add_directory 'tmp' add_php_file 'tmp', " eval('foo')" add_php_file 'tmp', "$_REQUEST" add_php_file 'tmp', "$wpdb->query(" add_non_php_file 'tmp' add_non_php_file 'tmp' scanner.scan "tmp" expect(output.string).to match(/Scanned 3 out of 5 files and found 3 things:/) end end end end end